第14章InnoDB存储引擎

目录

14.1 InnoDB简介
14.1.1使用InnoDB表的好处
14.1.2 InnoDB表的最佳实践
14.1.3验证InnoDB是默认存储引擎
14.1.4使用InnoDB进行测试和基准测试
14.1.5关闭InnoDB
14.2 InnoDB和ACID模型
14.3 InnoDB多版本控制
14.4 InnoDB体系结构
14.4.1缓冲池
14.4.2更改缓冲区
14.4.3自适应哈希索引
14.4.4重做日志缓冲区
14.4.5系统表空间
14.4.6 InnoDB数据字典
14.4.7双写缓冲区
14.4.8撤消日志
14.4.9每个文件表的表空间
14.4.10一般表空间
14.4.11撤消表空间
14.4.12临时表空间
14.4.13重做日志
14.5 InnoDB锁定和交易模型
14.5.1 InnoDB锁定
14.5.2 InnoDB事务模型
14.5.3在InnoDB中通过不同的SQL语句设置的锁
14.5.4幻影行
14.5.5 InnoDB中的死锁
14.6 InnoDB配置
14.6.1 InnoDB启动配置
14.6.2将InnoDB配置为只读操作
14.6.3 InnoDB缓冲池配置
14.6.4配置InnoDB的内存分配器
14.6.5配置InnoDB变更缓存
14.6.6配置InnoDB的线程并发
14.6.7配置背景InnoDB I / O线程数量
14.6.8在Linux上使用异步I / O
14.6.9配置InnoDB主线程I / O速率
14.6.10配置自旋锁定轮询
14.6.11配置InnoDB清除调度
14.6.12为InnoDB配置优化器统计信息
14.6.13为索引页面配置合并阈值
14.7 InnoDB表空间
14.7.1调整InnoDB系统表空间的大小
14.7.2更改InnoDB重做日志文件的数量或大小
14.7.3将原始磁盘分区用于系统表空间
14.7.4 InnoDB每个表文件的表空间
14.7.5在数据目录之外创建文件每表的表空间
14.7.6将文件 - 表 - 表 - 表空间复制到另一个实例
14.7.7配置撤消表空间
14.7.8截断撤消表空间
14.7.9 InnoDB常规表空间
14.7.10 InnoDB表空间加密
14.8 InnoDB表和索引
14.8.1 InnoDB表
14.8.2 InnoDB索引
14.9 InnoDB表和页面压缩
14.9.1 InnoDB表压缩
14.9.2 InnoDB页面压缩
14.10 InnoDB文件格式管理
14.10.1启用文件格式
14.10.2验证文件格式兼容性
14.10.3识别正在使用的文件格式
14.10.4修改文件格式
14.11 InnoDB行存储和行格式
14.11.1 InnoDB行存储概述
14.11.2指定表格的行格式
14.11.3动态和压缩行格式
14.11.4紧凑和冗余行格式
14.12 InnoDB磁盘I / O和文件空间管理
14.12.1 InnoDB磁盘I / O
14.12.2文件空间管理
14.12.3 InnoDB检查点
14.12.4对表进行碎片整理
14.12.5使用TRUNCATE TABLE回收磁盘空间
14.13 InnoDB和Online DDL
14.13.1在线DDL概述
14.13.2在线DDL性能,并发性和空间要求
14.13.3联机DDL SQL语法
14.13.4使用在线DDL简化DDL语句
14.13.5在线DDL实现细节
14.13.6在线DDL和崩溃恢复
14.13.7分区表的联机DDL
14.13.8在线DDL限制
14.14 InnoDB启动选项和系统变量
14.15 InnoDB INFORMATION_SCHEMA表
14.15.1 InnoDB INFORMATION_SCHEMA关于压缩的表
14.15.2 InnoDB INFORMATION_SCHEMA事务和锁定信息
14.15.3 InnoDB INFORMATION_SCHEMA系统表
14.15.4 InnoDB INFORMATION_SCHEMA FULLTEXT索引表
14.15.5 InnoDB INFORMATION_SCHEMA缓冲池表
14.15.6 InnoDB INFORMATION_SCHEMA度量表
14.15.7 InnoDB INFORMATION_SCHEMA临时表信息表
14.15.8从INFORMATION_SCHEMA.FILES中检索InnoDB表空间元数据
14.16 InnoDB与MySQL性能模式的集成
14.16.1使用性能模式监控InnoDB表的ALTER TABLE进度
14.16.2使用性能模式监控InnoDB互斥量等待
14.17 InnoDB监视器
14.17.1 InnoDB监视器类型
14.17.2启用InnoDB监视器
14.17.3 InnoDB标准监视器和锁定监视器输出
14.18 InnoDB备份和恢复
14.18.1 InnoDB备份
14.18.2 InnoDB恢复
14.19 InnoDB和MySQL复制
14.20 InnoDB memcached插件
14.20.1 InnoDB memcached插件的优点
14.20.2 InnoDB memcached架构
14.20.3设置InnoDB memcached插件
14.20.4 InnoDB memcached插件的安全注意事项
14.20.5编写InnoDB memcached插件的应用程序
14.20.6 InnoDB memcached插件和复制
14.20.7 InnoDB memcached插件内部
14.20.8解决InnoDB memcached插件故障
14.21 InnoDB故障排除
14.21.1排除InnoDB I / O问题
14.21.2强制InnoDB恢复
14.21.3 InnoDB数据字典操作故障排除
14.21.4 InnoDB错误处理

14.1 InnoDB简介

InnoDB是一款平衡高可靠性和高性能的通用存储引擎。在MySQL 5.7中,InnoDB是默认的MySQL存储引擎。除非您配置了其他默认存储引擎,否则发出CREATE TABLE不带ENGINE= 子句的语句会创建一个InnoDB表。

InnoDB的主要优势

表14.1 InnoDB存储引擎功能

特征 支持
B树索引
备份/时间点恢复(在服务器中实施,而不是在存储引擎中实施。)
集群数据库支持 没有
聚集索引
压缩数据
数据缓存
加密数据(通过加密功能在服务器中实现。静态数据表空间加密在MySQL 5.7和更高版本中可用。)
外键支持
全文搜索索引 是的(InnoDB对FULLTEXT索引的支持在MySQL 5.6和更高版本中可用。)
地理空间数据类型支持
地理空间索引支持 是的(InnoDB对地理空间索引的支持在MySQL 5.7和更高版本中可用。)
哈希索引 否(InnoDB在其内部使用散列索引来实现自适应散列索引功能。)
索引缓存
锁定粒度
MVCC
查询缓存支持
复制支持(在服务器中实现,而不是在存储引擎中实现。)
存储限制 64TB
T树索引 没有
交易
更新数据字典的统计信息

要比较InnoDB随MySQL提供的其他存储引擎的功能,请参阅第15章备用存储引擎中存储引擎功能

InnoDB增强功能和新功能

有关InnoDB增强功能和新功能的信息,请参阅:

额外的InnoDB信息和资源

14.1.1使用InnoDB表的好处

您可能会发现有InnoDB利于以下原因的表格:

  • 如果您的服务器因硬件或软件问题而崩溃,无论当时数据库中发生了什么情况,重新启动数据库后无需执行任何特殊操作。InnoDB 崩溃恢复会 自动完成崩溃前提交的任何更改,并撤消所有正在处理但未提交的更改。只需重新启动并继续你离开的地方。

  • InnoDB存储引擎维护它自己的 缓冲池,当数据被访问主内存中缓存表和索引数据。常用数据直接从内存中处理。此缓存适用于许多类型的信息并加速处理。在专用数据库服务器上,经常将高达80%的物理内存分配给缓冲池。

  • 如果将相关数据分解到不同的表中,则可以设置 强制执行 参照完整性的外键更新或删除数据,其他表中的相关数据会自动更新或删除。尝试将数据插入辅助表中,而主表中没有相应的数据,并且错误的数据会自动踢出。

  • 如果数据在磁盘或内存中损坏,则在使用它之前校验和机制会提醒您使用伪造数据。

  • 当您为每个表使用适当的主键设计数据库时 ,涉及这些列的操作会自动进行优化。引用WHERE 子句,ORDER BY子句, GROUP BY 子句和连接操作中的主键列是非常快的

  • 插入,更新和删除通过称为变更缓冲的自动机制进行优化InnoDB不仅可以对同一个表进行并发读取和写入访问,还可以缓存更改的数据以简化磁盘I / O。

  • 性能优势不限于具有长时间运行查询的巨型表。当从表中反复访问相同的行时,称为 自适应哈希索引的功能会继续执行,以使这些查找更快,就像它们从哈希表中出来一样。

  • 您可以压缩表和关联的索引。

  • 您可以创建和删除索引,而对性能和可用性影响更小。

  • 截断每个表文件表 空间非常快,可以腾出磁盘空间供操作系统重复使用,而不是释放系统表空间中只能InnoDB重用的空间

  • 表格数据的存储布局对于BLOB长文本字段和DYNAMIC行格式来说效率更高

  • 您可以通过查询INFORMATION_SCHEMA来监视存储引擎的内部运作情况

  • 您可以通过查询性能架构来监控存储引擎的性能细节

  • InnoDB即使在相同的语句中, 您也可以自由地将表与来自其他MySQL存储引擎的表混合例如,您可以使用 连接操作将单个查询中的数据InnoDBMEMORY表中的数据组合在一起

  • InnoDB 设计用于处理大量数据时的CPU效率和最高性能。

  • InnoDB 即使在文件大小限制为2GB的操作系统上,表格也可以处理大量数据。

对于InnoDB您可以在您的应用程序代码中应用的特定调优技术,请参见 第8.5节“优化InnoDB表”

14.1.2 InnoDB表的最佳实践

本节介绍使用InnoDB表格时的最佳做法

  • 使用最频繁查询的一列或多列 指定每个表主键 如果没有明显的主键,则指定一个 自动递增值。

  • 根据来自这些表的相同ID值从多个表中提取数据的地方 使用连接为了加快连接性能,请在连接列上定义 外键,并在每个表中声明具有相同数据类型的列。添加外键可确保引用的列进行索引,从而提高性能。外键还传播删除或更新所有受影响的表,并防止在父表中不存在相应的ID时将数据插入到子表中。

  • 关闭自动提交每秒提交数百次会限制性能(受存储设备写入速度的限制)。

  • 分组组相关的DML 操作成 交易,通过包围他们START TRANSACTIONCOMMIT报表。虽然你不想过于频繁地提交,你也不想发出的巨大的批次 INSERTUPDATE或者 DELETE,如果没有犯了几个小时运行的语句。

  • 不使用LOCK TABLES 语句。InnoDB可以一次处理多个会话全部读取和写入同一个表,而不会牺牲可靠性或高性能。要获得对一组行的独占写权限,请使用 SELECT ... FOR UPDATE语法来锁定您想要更新的行。

  • 启用该 innodb_file_per_table选项或使用常规表空间将表的数据和索引放入单独的文件中,而不是 系统表空间

    innodb_file_per_table 选项默认启用。

  • 评估您的数据和访问模式是否受益于InnoDB表或页面 压缩功能。您可以压缩InnoDB表而不牺牲读/写功能。

  • 使用选项运行服务器, --sql_mode=NO_ENGINE_SUBSTITUTION 以防止使用其他存储引擎创建表时,如果在ENGINE=子句中 指定的引擎有问题 CREATE TABLE

14.1.3验证InnoDB是默认存储引擎

发表SHOW ENGINES声明以查看可用的MySQL存储引擎。寻找 DEFAULTInnoDB行。

mysql> SHOW ENGINES;

或者,查询 INFORMATION_SCHEMA.ENGINES表格。

mysql> SELECT * FROM INFORMATION_SCHEMA.ENGINES;

14.1.4使用InnoDB进行测试和基准测试

如果InnoDB不是您的默认存储引擎,您可以InnoDB通过--default-storage-engine=InnoDB 在命令行中default-storage-engine=innodb 定义或者 [mysqld]MySQL服务器选项文件部分中定义的重新启动服务器 来确定数据库服务器或应用程序是否正常工作

由于更改默认存储引擎只会在创建新表时影响新表,请运行所有应用程序安装和设置步骤以确认所有事情都已正确安装。然后练习所有的应用程序功能,以确保所有数据加载,编辑和查询功能都能正常工作。如果表依赖于特定于其他存储引擎的功能,则会收到错误; 将该 子句添加 语句以避免错误。 ENGINE=other_engine_nameCREATE TABLE

如果您没有仔细决定存储引擎,并且想要预览某些表在创建时如何工作InnoDB,请ALTER TABLE table_name ENGINE=InnoDB;为每个表发出命令 或者,要运行测试查询和其他语句而不干扰原始表格,请复制一份:

CREATE TABLE InnoDB_Table(...)ENGINE = InnoDB AS SELECT * FROM other_engine_table;

要在真实工作负载下评估完整应用程序的性能,请安装最新的MySQL服务器并运行基准测试。

测试完整的应用程序生命周期,从安装到大量使用和服务器重新启动。在数据库繁忙期间终止服务器进程以模拟电源故障,并在重新启动服务器时验证数据是否已成功恢复。

测试任何复制配置,特别是如果您在主服务器和从服务器上使用不同的MySQL版本和选项。

14.1.5关闭InnoDB

Oracle建议InnoDB将其作为典型数据库应用程序的首选存储引擎,从单一用户维基和本地系统上运行的博客到推动性能极限的高端应用程序。在MySQL 5.7中,InnoDB是新表的默认存储引擎。

重要

InnoDB不能被禁用。--skip-innodb 选项已被弃用且无效,其使用会导致警告。它将在未来的MySQL版本中被删除。这也适用于它的同义词(--innodb=OFF--disable-innodb,等)。

14.2 InnoDB和ACID模型

ACID模式是一组数据库设计原则强调的是,对于业务数据和关键任务应用重要的可靠性方面。MySQL包含的组件如InnoDB存储引擎紧密结合ACID模型,以便数据不被破坏,并且结果不会因特殊情况(如软件崩溃和硬件故障)而失真。当您依赖ACID兼容功能时,您不需要重新发明一致性检查和崩溃恢复机制。如果您有其他软件保护措施,超可靠硬件或可以容忍少量数据丢失或不一致的应用程序,则可以调整MySQL设置以交换部分ACID可靠性以获得更高的性能或吞吐量。

以下各节讨论MySQL功能(特别是InnoDB存储引擎)如何 与ACID模型的类别进行交互:

  • :原子性。

  • C:一致性。

  • 我......隔离。

  • D:耐久性。

原子性

ACID模型原子性方面主要涉及InnoDB 交易相关的MySQL功能包括:

  • 自动提交设置。

  • COMMIT 声明。

  • ROLLBACK 声明。

  • 来自INFORMATION_SCHEMA 表格的操作数据

一致性

ACID模型一致性方面主要涉及内部InnoDB处理以保护数据免受崩溃。相关的MySQL功能包括:

隔离

ACID模型隔离方面主要涉及InnoDB 事务,特别是适用于每个事务隔离级别相关的MySQL功能包括:

  • 自动提交设置。

  • SET ISOLATION LEVEL 声明。

  • InnoDB 锁定 的低级细节在性能调优期间,您可以通过INFORMATION_SCHEMA表格查看这些细节

耐久力

ACID模型耐久性方面涉及MySQL软件功能与您的特定硬件配置进行交互。由于CPU,网络和存储设备的功能有很多可能性,因此提供具体的指导方针是最复杂的。(这些指南可能采取购买新硬件的形式 。)相关的MySQL功能包括:

  • InnoDB 双写缓冲区,由innodb_doublewrite 配置选项打开和关闭

  • 配置选项 innodb_flush_log_at_trx_commit

  • 配置选项 sync_binlog

  • 配置选项 innodb_file_per_table

  • 在存储设备(如磁盘驱动器,SSD或RAID阵列)中写入缓冲区。

  • 存储设备中的电池备份缓存。

  • 用于运行MySQL的操作系统,特别是它对fsync()系统调用的支持

  • 不间断电源(UPS)保护运行MySQL服务器和存储MySQL数据的所有计算机服务器和存储设备的电源。

  • 您的备份策略,例如备份频率和类型以及备份保留期。

  • 对于分布式或托管数据应用程序,MySQL服务器硬件所在数据中心的特定特征以及数据中心之间的网络连接。

14.3 InnoDB多版本控制

InnoDB是一个 多版本的存储引擎:它保存有关旧版本更改行的信息,以支持事务性功能,如并发和 回滚这些信息存储在表空间中的数据结构中,称为 回滚段(在Oracle中的类似数据结构之后)。InnoDB 使用回滚段中的信息执行事务回滚中所需的撤消操作。它还使用这些信息构建一个行的早期版本以进行 一致的读取

在内部,InnoDB为存储在数据库中的每一行添加三个字段。一个6字节的DB_TRX_ID字段表示插入或更新行的最后一个事务的事务标识符。另外,删除在内部被视为更新,其中行中的特殊位被设置为将其标记为删除。每行还包含一个DB_ROLL_PTR称为滚动指针的7字节 字段。滚动指针指向写入回滚段的撤消日志记录。如果该行已更新,则撤消日志记录包含在更新行之前重建该行内容所需的信息。一个6字节的DB_ROW_ID字段包含一个随着新行插入而单调递增的行ID。如果 InnoDB自动生成聚集索引,该索引包含行ID值。否则,该 DB_ROW_ID列不会出现在任何索引中。

撤销日志回滚段分为插入和更新撤消日志。插入撤消日志只在事务回滚中需要,并且只要事务提交就可以丢弃。更新撤消日志也用于一致性读取,但只有当没有事务存在时才会被丢弃,该事务 InnoDB已分配了一个快照,在一致的读取中可能需要更新撤消日志中的信息来构建数据库的较早版本行。

定期提交您的交易,包括只发布一致读取的交易。否则, InnoDB不能从更新撤消日志中丢弃数据,并且回滚段可能变得太大,从而填满你的表空间。

回滚段中撤销日志记录的物理大小通常小于相应的插入或更新行。您可以使用此信息来计算回滚段所需的空间。

InnoDB多版本方案中,当您使用SQL语句删除行时,行不会立即从数据库中物理删除。InnoDB只有在丢弃为删除而写入的更新撤消日志记录时,才会物理删除相应的行及其索引记录。这个删除操作称为清除,它非常快,通常与删除的SQL语句的时间顺序相同。

如果您在表格中以大致相同的速率插入和删除小批量行,则清除线程可能开始滞后,并且由于所有行,表可能变得越来越大 ,从而使得所有的磁盘都是磁盘绑定的,而且非常慢。在这种情况下,通过调整innodb_max_purge_lag系统变量来限制新行操作,并为清除线程分配更多资源 有关更多信息请参见第14.14节“InnoDB启动选项和系统变量”

多版本和二级索引

InnoDB多版本并发控制(MVCC)将二级索引视为与聚簇索引不同。聚集索引中的记录在原地更新,其隐藏系统列指向撤销日志条目,从中可以重建早期版本的记录。与聚集索引记录不同,二级索引记录不包含隐藏的系统列,也不就地更新。

当辅助索引列更新时,旧的辅助索引记录将被删除标记,插入新记录,最后清除删除标记的记录。当辅助索引记录被删除标记或辅助索引页面被更新的事务更新时,InnoDB查找聚集索引中的数据库记录。在聚集索引中,DB_TRX_ID检查记录,如果记录在读取事务启动后被修改,则从撤消日志中检索正确版本的记录。

如果辅助索引记录被标记为删除或者辅助索引页面被更新的事务更新, 则不使用覆盖索引技术。而不是从索引结构返回值,InnoDB查找聚集索引中的记录。

但是,如果启用索引条件下推(ICP)优化,并且WHERE可以仅使用索引中的字段来评估条件的某些部分,那么MySQL服务器仍然会将这部分WHERE条件下推到存储引擎,在该存储引擎中使用指数。如果找不到匹配的记录,则避免聚集索引查找。如果找到匹配的记录,即使在删除标记的记录中,也会 InnoDB查找聚集索引中的记录。

14.4 InnoDB体系结构

本节介绍InnoDB存储引擎体系结构的主要组件

14.4.1缓冲池

缓冲池是主存储器中的一个区域, InnoDB用于访问作为数据的缓存表和索引数据。缓冲池允许经常使用的数据直接从内存中处理,从而加快处理速度。在专用数据库服务器上,经常将高达80%的物理内存分配给InnoDB缓冲池。

为了提高高容量读取操作的效率,缓冲池分为可能包含多行的页面为了高速缓存管理的效率,缓冲池被实现为页面的链接列表; 很少使用的数据使用LRU算法的变体超时缓存

有关更多信息,请参见第14.6.3.1节“InnoDB缓冲池”第14.6.3节“InnoDB缓冲池配置”

14.4.2更改缓冲区

更改缓冲区是一种特殊的数据结构, 当受影响的页面不在缓冲池中,缓存对辅助索引页面的 更改缓冲的变化,这可能导致从 当页面被加载到由其他的读操作缓冲池操作(DML),将在后面合并。 INSERTUPDATEDELETE

聚簇索引不同,二级索引通常是不唯一的,插入到二级索引中会以相对随机的顺序进行。同样,删除和更新可能会影响不相邻位于索引树中的二级索引页。稍后合并缓存更改时,受影响的页面通过其他操作读入缓冲池时,可避免从磁盘读入二级索引页面所需的大量随机访问I / O。

定期地,当系统大部分处于空闲状态或缓慢关闭期间运行的清除操作会将更新后的索引页写入磁盘。与每个值立即写入磁盘相比,清除操作可以更有效地为一系列索引值写入磁盘块。

当需要更新许多二级索引和许多受影响的行时,更改缓冲区合并可能需要几个小时。在此期间,磁盘I / O会增加,这可能会导致磁盘绑定查询的显着减速。事务提交后,更改缓冲区合并也可能继续发生。事实上,在服务器关闭和重新启动后,更改缓冲区合并可能会继续发生(请参见 第14.21.2节“强制InnoDB恢复”以获取更多信息)。

在内存中,更改缓冲区占用了InnoDB缓冲池的一部分 在磁盘上,更改缓冲区是系统表空间的一部分,因此索引更改在数据库重新启动时保持缓冲。

缓存在更改缓冲区中的数据类型由 innodb_change_buffering 配置选项控制。有关更多信息,请参见 第14.6.5节“配置InnoDB更改缓冲”您还可以配置最大更改缓冲区大小。有关更多信息,请参见 第14.6.5.1节“配置更改缓冲区的最大大小”

监视更改缓冲区

以下选项可用于更改缓冲区监视:

  • InnoDB标准监视器输出包含更改缓冲区的状态信息。要查看监视器数据,请发出SHOW ENGINE INNODB STATUS 命令。

    MySQL的> SHOW ENGINE INNODB STATUS\G
    

    更改缓冲区状态信息位于INSERT BUFFER AND ADAPTIVE HASH INDEX 标题下方 并与以下内容类似:

    -------------------------------------
    INSERT BUFFER和ADAPTIVE HASH INDEX
    -------------------------------------
    Ibuf:大小1,空闲列表len 0,seg大小2,0合并
    合并操作:
     插入0,删除标记0,删除0
    丢弃的操作:
     插入0,删除标记0,删除0
    哈希表大小4425293,使用的单元32,节点堆有1个缓冲区(s)
    13577.57散列搜索/ s,202.47非散列搜索/ s
    

    有关更多信息,请参见 第14.17.3节“InnoDB标准监视器和锁定监视器输出”

  • INFORMATION_SCHEMA.INNODB_METRICS 表格提供了InnoDB标准监视器输出中的大部分数据点 以及其他数据点。要查看更改缓冲区度量标准及其每个描述,请发出以下查询:

    MySQL的> SELECT NAME, COMMENT FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME LIKE '%ibuf%'\G
    

    有关INNODB_METRICS表格使用信息,请参见 第14.15.6节“InnoDB INFORMATION_SCHEMA指标表”

  • INFORMATION_SCHEMA.INNODB_BUFFER_PAGE 表提供有关缓冲池中每个页面的元数据,包括更改缓冲区索引和更改缓冲区位图页面。更改缓冲区页面由标识 PAGE_TYPEIBUF_INDEX 是更改缓冲区索引页 IBUF_BITMAP的页面类型,是更改缓冲区位图页的页面类型。

    警告

    查询 INNODB_BUFFER_PAGE表可能会导致显着的性能开销。为避免影响性能,请重新创建要在测试实例上调查的问题,并在测试实例上运行查询。

    例如,您可以查询该 INNODB_BUFFER_PAGE表以确定大概的缓冲池页面数量 IBUF_INDEXIBUF_BITMAP页面总数的百分比。

    MySQL的> SELECT (SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
           WHERE PAGE_TYPE LIKE 'IBUF%') AS change_buffer_pages, 
           (SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE) AS total_pages,
           (SELECT ((change_buffer_pages/total_pages)*100)) 
           AS change_buffer_page_percentage;
    + --------------------- + ------------- ------------- + ------------------ +
    | change_buffer_pages | total_pages | change_buffer_page_percentage |
    + --------------------- + ------------- ------------- + ------------------ +
    | 25 | 8192 | 0.3052 |
    + --------------------- + ------------- ------------- + ------------------ +
    

    有关该INNODB_BUFFER_PAGE提供的其他数据的信息 ,请参见 第24.31.1节“INFORMATION_SCHEMA INNODB_BUFFER_PAGE表”有关相关使用信息,请参见 第14.15.5节“InnoDB INFORMATION_SCHEMA缓冲池表”

  • 性能架构 为高级性能监视提供了更改缓冲区互斥量等待检测。要查看更改缓冲区检测,请发出以下查询:

    MySQL的> SELECT * FROM performance_schema.setup_instruments
           WHERE NAME LIKE '%wait/synch/mutex/innodb/ibuf%';
    + ------------------------------------------------- ------ + --------- + ------- +
    | NAME | ENABLED | TIMED |
    + ------------------------------------------------- ------ + --------- + ------- +
    | wait / synch / mutex / innodb / ibuf_bitmap_mutex | 是| 是|
    | wait / synch / mutex / innodb / ibuf_mutex | 是| 是|
    | wait / synch / mutex / innodb / ibuf_pessimistic_insert_mutex | 是| 是|
    + ------------------------------------------------- ------ + --------- + ------- +
    

    有关监视InnoDB 互斥等待的信息,请参见 第14.16.2节“使用性能架构监视InnoDB互斥等待”

14.4.3自适应哈希索引

所述自适应散列索引(AHI)允许InnoDB执行更喜欢与工作量和用于充足存储器的适当组合,系统内存中的数据库 缓冲池,在不牺牲任何事务特性或可靠性。该功能由该innodb_adaptive_hash_index 选项启用 ,或--skip-innodb_adaptive_hash_index在服务器启动时关闭

根据观察到的搜索模式,MySQL使用索引键的前缀构建一个哈希索引。密钥的前缀可以是任意长度,并且可能只有B树中的某些值出现在哈希索引中。哈希索引是根据需要为经常访问的索引页面构建的。

如果一张表几乎完全适用于主内存,那么散列索引可以通过直接查找任何元素来加快查询速度,从而将索引值转换为一种指针。InnoDB 有一个监视索引搜索的机制。如果 InnoDB注意到查询可以从构建散列索引中受益,它会自动执行。

对于一些工作负载,散列索引查找的加速大大超过了监视索引查找和维护散列索引结构的额外工作。有时候,保护访问自适应散列索引的读/写锁可能成为工作负载繁重的争用源,如多个并发连接。查询与 LIKE运营商和% 通配符也不会从AHI中受益。对于不需要自适应散列索引的工作负载,将其关闭可减少不必要的性能开销。因为很难提前预测此功能是否适合特定系统,请考虑使用实际工作负载来启用和禁用启用和禁用基准。MySQL 5.6和更高版本中的架构更改使适用于禁用自适应哈希索引的工作负载比早期版本更适合,但默认情况下它仍处于启用状态。

在MySQL 5.7中,自适应散列索引搜索系统是分区的。每个索引都绑定到一个特定的分区,每个分区受独立的锁存器保护。分区由innodb_adaptive_hash_index_parts 配置选项控制 在早期版本中,自适应散列索引搜索系统受单个锁存器的保护,该锁存器在繁重的工作负载下可能成为争用点。innodb_adaptive_hash_index_parts 选项默认设置为8。最大设置是512。

散列索引始终基于表上现有的B树索引构建 InnoDB可以在为B树定义的任何密钥长度的前缀上构建一个哈希索引,具体取决于InnoDB观察到的B树索引的搜索模式散列索引可以是部分的,仅覆盖索引经常访问的那些页面。

您可以监视自适应哈希索引的使用SEMAPHORES 以及在SHOW ENGINE INNODB STATUS命令输出部分中 使用它的争用情况如果看到许多线程正在等待创建的RW锁存器btr0sea.c,那么禁用自适应散列索引可能会很有用。

有关散列索引性能特征的更多信息,请参见第8.3.8节“B树和散列索引的比较”

14.4.4重做日志缓冲区

重做日志缓冲区是保存要写入重做日志的数据的内存区域重做日志缓冲区大小由innodb_log_buffer_size 配置选项定义 重做日志缓冲区会定期刷新到磁盘上的日志文件。一个大的重做日志缓冲区允许大事务运行,而无需在事务提交之前将重做日志写入磁盘。因此,如果您有更新,插入或删除多行的事务,则使日志缓冲区更大可节省磁盘I / O。

innodb_flush_log_at_trx_commit 选项控制如何将重做日志缓冲区的内容写入日志文件。innodb_flush_log_at_timeout 选项控制重做日志刷新频率。

14.4.5系统表空间

所述InnoDB系统表空间包含的 InnoDB数据字典(元数据 InnoDB-相关对象)和对于双写缓冲器,所述缓冲器改变的存储区,并撤消日志。系统表空间还包含在系统表空间中创建的任何用户创建表的表和索引数据。系统表空间被视为共享表空间,因为它被多个表共享。

系统表空间由一个或多个数据文件表示。默认情况下,ibdata1在MySQL data目录中创建一个名为named的系统数据文件系统数据文件的大小和数量由innodb_data_file_path启动选项控制

有关相关信息,请参见 第14.6.1节“InnoDB启动配置”第14.7.1节“调整InnoDB系统表空间大小”

14.4.6 InnoDB数据字典

所述InnoDB数据字典包括包含用于跟踪对象,如表,索引,和表中的列的元数据的内部系统表。元数据物理上位于InnoDB系统表空间中。由于历史原因,数据字典元数据在一定程度上与存储在InnoDB表元数据文件(.frm文件)中的信息重叠

14.4.7双写缓冲区

双写缓冲区是一个位于系统表空间中的存储区域,在这个区域中,页面写入数据文件中的适当位置之前,缓冲池中的InnoDB页面被刷新InnoDB只有在刷新并将页面InnoDB写入双写缓冲区之后,才会 将页面写入其正确的位置。如果在页面写入过程中存在操作系统,存储子系统或 mysqld进程崩溃,InnoDB可以稍后在崩溃恢复期间从双写缓冲区中找到页面的良好副本。

尽管数据总是写入两次,但双写缓冲区不需要两倍的I / O开销或两倍的I / O操作。数据作为一个大的顺序块写入到双写缓冲区本身,只需一次fsync() 调用操作系统。

在大多数情况下,默认情况下会启用doublewrite缓冲区。要禁用双写缓冲区,请设置 innodb_doublewrite为0。

如果系统表空间文件(ibdata文件)位于支持原子写入的Fusion-io设备上,则会自动禁用双写缓冲,并将Fusion-io原子写入用于所有数据文件。由于双写缓冲区设置是全局性的,所以对于驻留在非Fusion-io硬件上的数据文件,也会禁用双写缓冲。此功能仅在Fusion-io硬件上受支持,并且仅适用于Linux上的Fusion-io NVMFS。要充分利用此功能,建议使用innodb_flush_method设置 O_DIRECT

14.4.8撤消日志

撤消日志是与单个事务关联的撤消日志记录的集合。撤销日志记录包含有关如何撤消事务对聚集索引 记录的最新更改的信息 如果另一个事务需要查看原始数据(作为一致读取操作的一部分),则从撤消日志记录中检索未修改的数据。撤销日志存在于 撤消日志段中,该日志段包含在 回滚段中回滚段位于 系统表空间临时表空间撤消表空间中有关更多信息,请参阅 第14.7.7节“配置撤消表空间”有关多版本控制的信息,请参见第14.3节“InnoDB多版本控制”

InnoDB支持128个回退段,其中32个保留为临时表事务的非重做回滚段。每个更新临时表(不包括只读事务)的事务都被分配了两个回滚段,一个启用了重做的回滚段和一个非重做回滚段。只读事务只分配非重做回滚段,因为只读事务只允许修改临时表。

这留下了96个可用回滚段,每个回滚段支持多达1023个并发数据修改事务,总共限制大约96K个并发数据修改事务。96K限制假定事务不修改临时表。如果所有数据修改事务也修改临时表,则总数限制约为32K个并发数据修改事务。有关为临时表事务保留的回滚段的更多信息,请参见 临时表撤消日志

innodb_rollback_segments 选项定义了使用的回退段的数量 InnoDB

14.4.9每个文件表的表空间

每个文件表的表空间是一个单独的表空间,它是在它自己的数据文件中创建的,而不是在系统表空间中创建的。innodb_file_per_table启用选项时,将在每个文件表格空间中创建表格 否则,InnoDB将在系统表空间中创建表。每个每个文件表的表空间由单个.ibd数据文件表示,该数据文件默认在数据库目录中创建。

文件每表的表空间支持DYNAMICCOMPRESSED行格式支持诸如用于可变长度数据和表压缩的离页存储之类的功能。有关这些功能以及file-per-table表空间的其他优点的信息,请参见 第14.7.4节“InnoDB每个表文件的表空间”

14.4.10一般表空间

InnoDB使用CREATE TABLESPACE语法创建 的共享表空间 常规表空间可以在MySQL数据目录之外创建,能够保存多个表,并支持所有行格式的表。

表使用语法添加到常规表空间 CREATE TABLE tbl_name ... TABLESPACE [=] tablespace_nameALTER TABLE tbl_name TABLESPACE [=] tablespace_name

有关更多信息,请参见第14.7.9节“InnoDB常规表空间”

14.4.11撤消表空间

撤消表空间包含一个或多个包含撤消日志的文件 使用的撤消表空间的数量InnoDBinnodb_undo_tablespaces 配置选项定义 有关更多信息,请参见 部分14.7.7,“配置撤消表空间”

注意

innodb_undo_tablespaces 已弃用,将在未来版本中删除。

14.4.12临时表空间

非压缩的用户创建的临时表和磁盘内部临时表是在共享的临时表空间中创建的。innodb_temp_data_file_path 配置选项定义了相对路径,名称,规格,和用于临时表空间的数据文件属性。如果未指定值 innodb_temp_data_file_path,则缺省行为是ibtmp1innodb_data_home_dir目录中创建一个自动扩展数据文件,该 文件的名称 略大于12MB。

压缩的临时表(使用该ROW_FORMAT=COMPRESSED属性创建 的临时表)是在临时文件目录中的文件 - 每表中的空间中创建的

临时表空间在正常关闭或中止初始化时被删除,并在每次启动服务器时重新创建。临时表空间在创建时接收动态生成的空间ID。如果无法创建临时表空间,则启动将被拒绝。如果服务器意外停止,则不会删除临时表空间。在这种情况下,数据库管理员可以手动删除临时表空间或重新启动服务器,该服务器会自动删除并重新创建临时表空间。

临时表空间不能驻留在原始设备上。

INFORMATION_SCHEMA.FILES提供有关InnoDB临时表空间的元数据发出与此类似的查询来查看临时表空间元数据:

MySQL的> SELECT * FROM INFORMATION_SCHEMA.FILES WHERE TABLESPACE_NAME='innodb_temporary'\G

INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO 提供有关在InnoDB实例中当前活动的用户创建的临时表的元数据有关更多信息,请参见 第14.15.7节“InnoDB INFORMATION_SCHEMA临时表信息表”

管理临时表空间数据文件大小

默认情况下,临时表空间数据文件是自动扩展的,并根据需要增加大小以适应磁盘上的临时表。例如,如果某个操作创建了一个大小为20 MB的临时表,则创建时默认大小为12 MB的临时表空间数据文件会扩展以适应该表。当删除临时表时,释放的空间可以重新用于新的临时表,但数据文件保持扩展大小。

在使用大型临时表或广泛使用临时表的环境中,自动扩展临时表空间数据文件可能会变大。长时间运行的使用临时表的查询也可能导致大型数据文件。

要确定临时表空间数据文件是否自动扩展,请检查 innodb_temp_data_file_path 设置:

MySQL的> SELECT @@innodb_temp_data_file_path;
+ ------------------------------ +
| @@ innodb_temp_data_file_path |
+ ------------------------------ +
| ibtmp1:12M:autoextend |
+ ------------------------------ +

要检查临时表空间数据文件的大小,请INFORMATION_SCHEMA.FILES使用类似下面的查询来查询 表:

MySQL的> SELECT FILE_NAME, TABLESPACE_NAME, ENGINE, INITIAL_SIZE, TOTAL_EXTENTS*EXTENT_SIZE 
       AS TotalSizeBytes, DATA_FREE, MAXIMUM_SIZE FROM INFORMATION_SCHEMA.FILES 
       WHERE TABLESPACE_NAME = 'innodb_temporary'\G
*************************** 1. row ******************** *******
      FILE_NAME:./ibtmp1
TABLESPACE_NAME:innodb_temporary
         ENGINE:InnoDB
   INITIAL_SIZE:12582912
 TotalSizeBytes:12582912
      DATA_FREE:6291456
   MAXIMUM_SIZE:NULL

TotalSizeBytes值报告临时表空间数据文件的当前大小。有关其他字段值的信息,请参见第24.8节“INFORMATION_SCHEMA文件表”

或者,您可以检查操作系统上的临时表空间数据文件大小。默认情况下,临时表空间数据文件位于由innodb_temp_data_file_path 配置选项定义的目录中 如果未明确指定此选项的值,ibtmp1则会创建 一个名为临时表空间数据文件,如果未指定,该文件将 innodb_data_home_dir默认为MySQL数据目录。

要回收临时表空间数据文件占用的磁盘空间,可以重新启动MySQL服务器。重新启动服务器将根据定义的属性删除并重新创建临时表空间数据文件 innodb_temp_data_file_path

为防止临时数据文件变得过大,可以配置该 innodb_temp_data_file_path 选项以指定最大文件大小。例如:

的[mysqld]
innodb_temp_data_file_path = ibtmp1:12M:自动扩展:最大:500M

当数据文件达到最大大小时,查询将失败,并显示表已满的错误。配置 innodb_temp_data_file_path 需要重新启动服务器。

或者,您可以配置 default_tmp_storage_engineinternal_tmp_disk_storage_engine 选项,它们分别定义用于用户创建的和磁盘上的内部临时表的存储引擎。这两个选项InnoDB默认设置为MyISAM存储引擎使用用于每个临时表,当临时表被删除被去除单个文件。

临时表撤消日志

临时表撤消日志驻留在临时表空间中,用于临时表和相关对象。临时表撤消日志不会被重新记录,因为它们不是崩溃恢复所必需的。它们仅用于服务器运行时的回滚。这种特殊类型的撤消日志通过避免重做日志I / O来提高性能。对于修改临时表和相关对象的事务, 将为临时表撤消日志保留 32个 回滚段

14.4.13重做日志

重做日志是在崩溃恢复期间使用的基于磁盘的数据结构,用于纠正由不完整事务写入的数据。在正常操作期间,重做日志将编码请求以更改 InnoDB由SQL语句或低级别API调用产生的表数据。在意外关闭之前没有完成更新数据文件的修改会在初始化期间以及接受连接之前自动重播。有关重做日志在崩溃恢复中的角色的信息,请参见第14.18.2节“InnoDB恢复”

默认情况下,重做日志在物理上表现为一组文件,名为ib_logfile0ib_logfile1MySQL以循环方式写入重做日志文件。重做日志中的数据按受影响的记录进行编码; 这些数据统称为重做。数据通过重做日志的过程由不断增加的LSN值表示。

有关相关信息,请参阅:

14.4.13.1重做日志刷新的组提交

InnoDB与任何其他 ACID兼容的数据库引擎一样,在事务提交之前刷新事务重做日志InnoDB 使用组提交 功能将多个此类刷新请求组合在一起,以避免每次提交都有一次刷新。通过组提交, InnoDB向日志文件发出一次写入操作,以便为大约同时提交的多个用户事务执行提交操作,从而显着提高吞吐量。

有关性能COMMIT和其他事务操作的更多信息 ,请参见第8.5.2节“优化InnoDB事务管理”

14.5 InnoDB锁定和交易模型

要实现大型,繁忙或高度可靠的数据库应用程序,移植来自不同数据库系统的实际代码或调整MySQL性能,理解InnoDB锁定和InnoDB 事务模型非常重要

本节讨论与InnoDB锁定有关的几个主题 以及InnoDB 您应该熟悉事务模型。

14.5.1 InnoDB锁定

本节介绍由使用的锁类型 InnoDB

共享和独占锁

InnoDB在有两种类型的锁共享(S)锁独占(X)锁的情况下实现标准行级锁定

如果事务在行上T1保存共享(S)锁r,那么来自某个不同事务T2的对行的锁的请求 r按如下方式处理:

  • 由A请求T2用于 S锁可以立即被授予。其结果是,无论是T1T2持有S 的锁r

  • 通过请求T2一个 X锁不能立即授予。

如果一个事务T1持有一个exclusive(X)锁定行r则不能立即授予来自某个不同事务的T2 对任一类型锁的请求r相反,事务T2 必须等待事务T1才能释放行上的锁r

意图锁定

InnoDB支持多个粒度锁定,允许行锁和表锁共存。例如,诸如 对指定表LOCK TABLES ... WRITE进行独占锁定(X锁定)的语句 为了实现多个粒度级别的锁定,InnoDB使用 意向锁意向锁是表级锁,用于指示事务对表中某一行的事务需要哪种类型的锁(共享或排他)。有两种类型的意向锁:

  • 意图共享锁IS)指示一个事务打算设置一个共享 上各个行锁定在表中。

  • 意图独占锁IX)指示一个事务打算设定各行的排他锁在表中。

例如,SELECT ... LOCK IN SHARE MODE设置一个IS锁,并SELECT ... FOR UPDATE设置一个IX锁。

意向锁定协议如下:

  • 在一个事务可以获取表中一行上的共享锁之前,它必须先获得一个IS锁或更强的表。

  • 在一个事务可以获得一个表中某一行的排它锁之前,它必须首先获得IX 该表的一个锁。

表级锁定类型的兼容性总结在下面的矩阵中。

X IX S IS
X 冲突 冲突 冲突 冲突
IX 冲突 兼容 冲突 兼容
S 冲突 冲突 兼容 兼容
IS 冲突 兼容 兼容 兼容

如果请求事务与现有的锁定兼容,则授予锁定,但如果它与现有的锁定冲突,则该锁定不会被授予。事务一直等到冲突的现有锁被释放。如果锁定请求与现有的锁冲突并且因为会导致死锁而无法被授予 ,则会发生错误。

意向锁不会阻止除完整表请求之外的任何内容(例如,LOCK TABLES ... WRITE)。意向锁的主要目的是显示某人正在锁定一行,或者要锁定表中的一行。

意向锁定的交易数据SHOW ENGINE INNODB STATUSInnoDB监视器 输出中的以下内容类似

TABLE LOCK table`test`.`t` trx id 10080锁定模式IX

记录锁定

记录锁是索引记录上的锁。例如, SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE; 可以防止从插入,更新或删除行,其中的值的任何其它交易t.c110

即使没有索引定义表,记录锁始终锁定索引记录。对于这种情况, InnoDB创建一个隐藏的聚集索引并使用此索引进行记录锁定。请参见 第14.8.2.1节“聚集索引和二级索引”

记录锁定的事务数据SHOW ENGINE INNODB STATUSInnoDB监视器 输出中的以下内容类似

记录锁定space id 58 page no 3 n bits 72 index`PRIMARY` table`test`.`t` 
trx id 10078 lock_mode X锁定rec,但不锁定
记录锁定,堆号2物理记录:n_fields 3; 紧凑格式; 信息位0
 0:len 4; 六千八百〇万; asc ;;
 1:len 6; 十六进制00000000274f; asc'O ;;
 2:len 7; 十六进制b60000019d0110; asc ;;

间隙锁

间隙锁定是索引记录之间的间隙的锁定,或者是第一个或最后一个索引记录之前的间隙锁定。例如,SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE;阻止其他事务15向列中插入值t.c1,而不管中是否已有任何此类值,因为范围内所有现有值之间的间隔都是锁定的。

间隔可能跨越单个索引值,多个索引值,甚至是空的。

间隙锁是性能和并发性之间折中的一部分,并且在某些事务隔离级别中使用,而不是在其他级别中使用。

对于使用唯一索引锁定行以搜索唯一行的语句,不需要使用间隙锁定。(这不包括搜索条件仅包含多列唯一索引中的某些列的情况;在这种情况下,会发生间隙锁定)。例如,如果id列具有唯一索引,则以下语句只使用索引记录锁定id值为100 的行,并且其他会话是否在上述间隔中插入行并不重要:

SELECT * FROM child WHERE id = 100;

如果id未被索引或者具有非唯一索引,则该语句确实锁定了前面的差距。

这里也值得注意的是,不同交易可以在差距上保持冲突的锁定。例如,事务A可以在间隔上保存共享间隙锁(间隙S锁),而事务B在同一间隙上保留独占间隙锁(间隙X锁)。允许冲突间隙锁定的原因是,如果从索引中清除记录,则必须合并由不同事务记录保存的间隙锁定。

缺口锁定InnoDB纯粹抑制性的,这意味着它们只能阻止其他交易进入缺口。它们不会阻止不同的交易在同一个差距上进行差距锁定。因此,间隙X锁具有与间隙S锁相同的效果。

可以显式禁用间隙锁定。如果将事务隔离级别更改为READ COMMITTED或启用 innodb_locks_unsafe_for_binlog 系统变量(现在已弃用),则会发生这种情况 在这些情况下,对搜索和索引扫描禁用间隙锁定,仅用于外键约束检查和重复键检查。

还有使用READ COMMITTED隔离级别或启用的 其他影响 innodb_locks_unsafe_for_binlog在MySQL评估WHERE条件之后,释放不匹配行的记录锁对于 UPDATE语句,InnoDB 执行半连续读取,以便它将最新的提交版本返回给MySQL,以便MySQL可以确定该行是否匹配WHERE 条件UPDATE

Next-Key锁

下一个键锁定是索引记录上的记录锁定和索引记录之前的间隙上的间隙锁定的组合。

InnoDB以这样的方式执行行级锁定,即当它搜索或扫描表索引时,它会在遇到的索引记录上设置共享锁或排它锁。因此,行级锁实际上是索引记录锁。索引记录上的下一个键锁定还会影响该索引记录之前间隙也就是说,下一个键锁定是索引记录锁定,并在索引记录之前的间隔上加上间隙锁定。如果一个会话R在索引中具有记录中的共享或排它锁定 ,则另一个会话不能R在索引顺序中立即在间隙中插入新的索引记录

假设索引包含值10,11,13和20.此索引的可能下一个键锁定涵盖以下区间,其中圆括号表示排除区间端点,方括号表示包含端点:

(负无穷,10)
(10,11]
(11,13]
(13,20]
(20,正无穷)

对于最后一个时间间隔,下一个键锁定将索引中最大值以上的间隔锁定,并且上游 伪记录的值高于实际在索引中的任何值。上确界不是真实的索引记录,因此,实际上,这个下一个键锁只锁定最大索引值之后的间隔。

默认情况下,InnoDBREPEATABLE READ事务隔离级别运行。在这种情况下,InnoDB使用下一个键锁进行搜索和索引扫描,这可以防止幻像行(请参见第14.5.4节“幻像行”)。

下一个键锁定的事务数据SHOW ENGINE INNODB STATUSInnoDB监视器 输出中的以下内容类似

记录锁定space id 58 page no 3 n bits 72 index`PRIMARY` table`test`.`t` 
trx id 10080 lock_mode X
记录锁定,堆号1物理记录:n_fields 1; 紧凑格式; 信息位0
 0:len 8; 十六进制73757072656d756d; asc supremum ;;

记录锁定,堆号2物理记录:n_fields 3; 紧凑格式; 信息位0
 0:len 4; 六千八百〇万; asc ;;
 1:len 6; 十六进制00000000274f; asc'O ;;
 2:len 7; 十六进制b60000019d0110; asc ;;

插入意向锁

插入意向锁定是INSERT在行插入之前通过操作设置的一种间隙锁定 这个锁定以插入到相同索引间隙中的多个事务不需要等待对方的方式插入的意图,如果它们没有插入间隙中的相同位置。假设有索引记录的值为4和7.单独的事务试图分别插入5和6的值,每个事务都在插入行上获得排它锁之前用插入意向锁来锁定4和7之间的间隔,但不要相互阻塞,因为这些行是非冲突的。

以下示例演示了在获取插入记录的排它锁之前,插入意向锁的事务。这个例子涉及两个客户,A和B.

客户端A创建一个包含两个索引记录(90和102)的表,然后启动一个事务处理,对ID大于100的索引记录进行排它锁定。排它锁包括记录102之前的间隔锁:

mysql> CREATE TABLE child (id int(11) NOT NULL, PRIMARY KEY(id)) ENGINE=InnoDB;
mysql>INSERT INTO child (id) values (90),(102);

mysql> START TRANSACTION;
mysql>SELECT * FROM child WHERE id > 100 FOR UPDATE;
+ ----- +
| id |
+ ----- +
| 102 |
+ ----- +

客户B开始交易以将记录插入到间隙中。该事务在等待获得排他锁的同时获取插入意向锁。

mysql> START TRANSACTION;
mysql>INSERT INTO child (id) VALUES (101);

插入意图锁定的事务数据SHOW ENGINE INNODB STATUSInnoDB监视器 输出中的以下内容类似

记录锁定空间ID 31页面号3 n位72索引表'test`.`child`的`PRIMARY`
trx id 8731 lock_mode X在插入意图等待之前锁定间隙
记录锁,堆号3物理记录:n_fields 3; 紧凑格式; 信息位0
 0:len 4; 六角形80000066; asc f ;;
 1:len 6; 十六进制000000002215; asc“;;
 2:len 7; 六角9000000172011c; asc r ;; ...

AUTO-INC锁定

一个AUTO-INC锁是通过交易将与表中取得一个特殊的表级锁 AUTO_INCREMENT列。在最简单的情况下,如果一个事务将值插入到表中,则任何其他事务都必须等待对该表执行自己的插入操作,以便第一个事务插入的行接收连续的主键值。

innodb_autoinc_lock_mode 配置选项控制用于自动增加锁定的算法。它允许您选择如何在可预测的自动递增值序列和插入操作的最大并发之间进行权衡。

有关更多信息,请参见 第14.8.1.5节“InnoDB中的AUTO_INCREMENT处理”

谓词锁定空间索引

InnoDB支持SPATIAL 对包含空间列的列进行索引(参见 第11.5.8节“优化空间分析”)。

要处理涉及SPATIAL索引的操作的锁定 ,下一个键锁定对支持REPEATABLE READSERIALIZABLE事务隔离级别不起作用多维数据中没有绝对的排序概念,因此不清楚哪个是 下一个键。

要为具有SPATIAL索引的表启用支持隔离级别 ,请InnoDB 使用谓词锁。SPATIAL索引包含最小外接矩形(MBR)值,因此, InnoDB通过设置用于查询的MBR值的谓词锁强制上的索引一致的读取。其他事务不能插入或修改与查询条件匹配的行。

14.5.2 InnoDB事务模型

InnoDB事务模型中,目标是将多版本数据库的最佳属性 与传统的两阶段锁定相结合。默认情况下,按照Oracle的风格,InnoDB在行级别执行锁定并将查询作为非锁定一致读取运行 锁定信息 InnoDB存储在空间中,因此不需要锁定升级。通常,允许多个用户锁定InnoDB表中的每一行或任何行的随机子集,而不会导致 InnoDB内存耗尽。

14.5.2.1事务隔离级别

事务隔离是数据库处理的基础之一。隔离是I的首字母缩写 ACID ; 隔离级别是在多个事务进行更改并同时执行查询时,对性能和可靠性之间的平衡,结果的一致性和再现性进行微调的设置。

InnoDB提供由SQL描述的所有四个事务隔离级别:1992标准: READ UNCOMMITTEDREAD COMMITTEDREPEATABLE READ,和 SERIALIZABLEInnoDBis 的默认隔离级别REPEATABLE READ

用户可以更改单个会话的隔离级别,也可以更改该SET TRANSACTION语句的所有后续连接要为所有连接设置服务器的默认隔离级别,请使用 --transaction-isolation命令行或选项文件中的选项。有关隔离级别和级别设置语法的详细信息,请参见 第13.3.6节“SET TRANSACTION语法”

InnoDB支持使用不同的锁定策略在此描述的每个事务隔离级别 您可以强制执行与默认REPEATABLE READ级别的高度一致性 ,以便对符合ACID要求的关键数据进行操作 或者,您可以放宽一致性规则, READ COMMITTED甚至 READ UNCOMMITTED在批量报告等情况下,精确的一致性和可重复的结果不如最小化锁定开销的数量重要。 SERIALIZABLE执行更严格的规则REPEATABLE READ,而且主要用于特殊情况下,如XA事务和解决并发和死锁问题

以下列表描述了MySQL如何支持不同的事务级别。该列表从最常用的级别到最少使用的级别。

  • REPEATABLE READ

    这是默认的隔离级别 InnoDB 在同一事务中的一致读取读取第一次读取建立快照这意味着,如果您SELECT 在同一个事务中发出多个纯(非锁定)语句,这些 SELECT语句在彼此之间也是一致的。请参见 第14.5.2.3节“一致性非锁定读取”

    对于锁定读取SELECT使用FOR UPDATELOCK IN SHARE MODE), UPDATEDELETE语句,锁定取决于语句是使用具有唯一搜索条件的唯一索引还是范围类型搜索条件。

    • 对于具有唯一搜索条件的唯一索引, InnoDB仅锁定找到的索引记录,而不是锁定 之前间隔

    • 对于其他搜索条件,InnoDB 使用间隙锁下一个键锁锁定扫描的索引范围, 以阻止其他会话插入到范围所覆盖的间隙中。有关间隙锁和下一个键锁的信息,请参见 第14.5.1节“InnoDB锁定”

  • READ COMMITTED

    即使在同一个事务中,每次一致的读取都会设置并读取其自己的新快照。有关一致读取的信息,请参见 第14.5.2.3节“一致性非锁定读取”

    对于锁定读取(SELECT 使用FOR UPDATELOCK IN SHARE MODE),UPDATE 语句和DELETE 语句,InnoDB只锁定索引记录,而不锁定它们之前的间隔,从而允许在锁定记录旁边自由插入新记录。间隙锁定仅用于外键约束检查和重复键检查。

    由于禁用了间隙锁定,所以可能会出现幻影问题,因为其他会话可以将新行插入到间隙中。有关幻影的信息,请参见 第14.5.4节“幻影行”

    如果您使用READ COMMITTED,则 必须使用基于行的二进制日志记录。

    使用READ COMMITTED有其他影响:

    • 对于UPDATEDELETE语句, InnoDB仅锁定更新或删除的行。在MySQL评估WHERE条件之后,释放不匹配行的记录锁 这大大降低了死锁的可能性,但它们仍然可能发生。

    • 对于UPDATE语句,如果某行已被锁定,则InnoDB 执行半连续读取,将最新的已提交版本返回给MySQL,以便MySQL可以确定该行是否与该WHERE条件 匹配 UPDATE如果行匹配(必须更新),MySQL会再次读取该行,并且这次InnoDB会锁定它或等待锁定。

    考虑下面的例子,从这个表开始:

    CREATE TABLE t(INT NOT NULL,b INT)ENGINE = InnoDB;
    插入t值(1,2),(2,3),(3,2),(4,3),(5,2);
    承诺;
    

    在这种情况下,该表没有索引,因此搜索和索引扫描使用隐藏聚簇索引进行记录锁定(请参见第14.8.2.1节“聚簇索引”和“二级索引”)而不是索引列。

    假设一个会话UPDATE使用这些语句执行

    #会话A
    开始交易;
    UPDATE t SET b = 5 WHERE b = 3;
    

    假设第二个会话 UPDATE通过在第一个会话之后执行这个语句来执行:

    #会话B
    UPDATE t SET b = 4 WHERE b = 2;
    

    由于InnoDB每个执行 UPDATE时,它首先获取用于它读取,并且然后确定是否要修改它的每一行的排他锁。如果 InnoDB不修改该行,则释放该锁。否则, InnoDB保留锁直到交易结束。这会影响事务处理,如下所示。

    当使用默认REPEATABLE READ 隔离级别时,第 UPDATE一个在它读取的每一行上获取一个x锁,并且不释放它们中的任何一个:

    X锁(1,2); 保留x锁
    X锁(2,3); 更新(2,3)至(2,5); 保留x锁
    X锁(3,2); 保留x锁
    X锁(4,3); 更新(4,3)至(4,5); 保留x锁
    X锁(5,2); 保留x锁
    

    第二次UPDATE尝试获取任何锁(因为第一次更新保留了所有行上的锁)就立即阻塞,直到第一次UPDATE提交或回滚时才会继续

    X锁(1,2); 阻止并等待第一个UPDATE提交或回滚
    

    如果READ COMMITTED使用它,第UPDATE一个会在它读取的每一行上获取一个x-lock,并为那些未修改的行释放它们:

    X锁(1,2); 解锁(1,2)
    X锁(2,3); 更新(2,3)至(2,5); 保留x锁
    X锁(3,2); 解锁(3,2)
    X锁(4,3); 更新(4,3)至(4,5); 保留x锁
    X锁(5,2); 解锁(5,2)
    

    对于第二种情况UPDATEInnoDB执行 半连续读取,将其读取的每一行的最新提交版本返回给MySQL,以便MySQL可以确定该行是否与以下WHERE条件 匹配 UPDATE

    X锁(1,2); 更新(1,2)至(1,4); 保留x锁
    X锁(2,3); 解锁(2,3)
    X锁(3,2); 更新(3,2)至(3,4); 保留x锁
    X锁(4,3); 解锁(4,3)
    X锁(5,2); 更新(5,2)至(5,4); 保留x锁
    

    但是,如果WHERE条件包含索引列并InnoDB使用该索引,则在获取和保留记录锁时仅考虑索引列。在下面的例子中,第 UPDATE一个在b = 2的每一行上获取并保留一个x锁。UPDATE当它尝试获取相同记录上的x锁时,第二个 块会使用在列b上定义的索引。

    CREATE TABLE t(INT NOT NULL,b INT,c INT,INDEX(b))ENGINE = InnoDB;
    插入t值(1,2,3),(2,2,4);
    承诺;
    
    #会话A
    开始交易;
    UPDATE t SET b = 3 WHERE b = 2 AND c = 3;
    
    #会话B
    UPDATE t SET b = 4 WHERE b = 2 AND c = 4;
    

    使用READ COMMITTED 隔离级别的效果与启用不建议的 innodb_locks_unsafe_for_binlog 配置选项相同,但有以下例外:

    • 启用 innodb_locks_unsafe_for_binlog 是一个全局设置,会影响所有会话,而隔离级别可以全局设置为所有会话,也可以单独设置每个会话。

    • innodb_locks_unsafe_for_binlog 只能在服务器启动时设置,而隔离级别可以在启动时设置或在运行时更改。

    READ COMMITTED因此提供更好,更灵活的控制 innodb_locks_unsafe_for_binlog

  • READ UNCOMMITTED

    SELECT语句以非锁定方式执行,但可能会使用一个可能的早期版本的行。因此,使用这种隔离级别,这样的读取不一致。这也被称为 脏读否则,这个隔离级别就像 READ COMMITTED

  • SERIALIZABLE

    这个级别就像REPEATABLE READ,但InnoDB隐式地将所有简单SELECT 语句转换SELECT ... LOCK IN SHARE MODEif autocommit被禁用。如果 autocommit启用,则 SELECT是它自己的事务。因此,它被认为是只读的,并且如果作为一致(非锁定)读取执行,则可以被序列化,并且不需要阻塞其他事务。SELECT如果其他事务修改了选定的行,强制平原 阻止,请禁用 autocommit。)

14.5.2.2自动提交,提交和回滚

在中InnoDB,所有的用户活动都发生在一个事务中。如果autocommit启用了模式,则每个SQL语句都会自行形成一个事务。默认情况下,MySQL在autocommit 启用时为每个新连接启动会话,所以如果该语句没有返回错误,则MySQL会在每个SQL语句后执行提交。如果语句返回错误,则提交或回滚行为取决于错误。请参见 第14.21.4节“InnoDB错误处理”

具有会话autocommit 启用可以通过显式启动它执行多语句事务 START TRANSACTIONBEGIN 语句,并用它结束 COMMITROLLBACK 声明。请参见第13.3.1节“START TRANSACTION,COMMIT和ROLLBACK语法”

如果autocommit模式在会话中被禁用SET autocommit = 0,则会话始终打开一个事务。A COMMITROLLBACK 语句结束当前交易并开始新交易。

如果一个autocommit没有明确提交最终事务的禁用会话 结束,MySQL会回滚该事务。

一些语句隐式地结束了一个事务,就好像你COMMIT在执行语句之前完成了一样。有关详细信息,请参见第13.3.3节“导致隐式提交的语句”

COMMIT意味着在当前交易中所做的更改将永久化,并对其他会话可见。一个 ROLLBACK 声明,而另一方面,取消当前事务中的所有修改。双方 COMMITROLLBACK 释放所有InnoDB当前事务期间设置的锁。

用事务对DML操作进行分组

默认情况下,连接到MySQL服务器开始与 自动提交模式启用,当你执行它自动提交每个SQL语句。如果您对其他数据库系统有经验,那么这种操作模式可能并不熟悉,在这种模式下,发布一系列DML语句并提交它们或将它们一起回滚是标准做法

要使用多语句 事务,开关自动提交了与SQL语句SET autocommit = 0,并结束与每一笔交易 COMMITROLLBACK为合适。要使自动提交功能开启,请START TRANSACTION使用COMMIT开始每个事务并以其结束 ROLLBACK以下示例显示了两个事务。第一个承诺; 第二个回滚。

外壳> mysql test
MySQL的> CREATE TABLE customer (a INT, b CHAR (20), INDEX (a));
查询OK,0行受影响(0.00秒)
mysql> -- Do a transaction with autocommit turned on.
mysql>START TRANSACTION;
查询OK,0行受影响(0.00秒)
MySQL的> INSERT INTO customer VALUES (10, 'Heikki');
查询OK,1行受影响(0.00秒)
MySQL的> COMMIT;
查询OK,0行受影响(0.00秒)
mysql> -- Do another transaction with autocommit turned off.
mysql>SET autocommit=0;
查询OK,0行受影响(0.00秒)
MySQL的> INSERT INTO customer VALUES (15, 'John');
查询OK,1行受影响(0.00秒)
MySQL的> INSERT INTO customer VALUES (20, 'Paul');
查询OK,1行受影响(0.00秒)
MySQL的> DELETE FROM customer WHERE b = 'Heikki';
查询OK,1行受影响(0.00秒)
mysql> -- Now we undo those last 2 inserts and the delete.
mysql>ROLLBACK;
查询OK,0行受影响(0.00秒)
MySQL的> SELECT * FROM customer;
+ ------ + -------- +
| a | b |
+ ------ + -------- +
| 10 | Heikki |
+ ------ + -------- +
一排(0.00秒)
MySQL的>
客户端语言事务

在诸如PHP,Perl DBI,JDBC,ODBC或MySQL的标准C调用接口之类的API中,您可以将事务控制语句(例如COMMIT任何其他SQL语句(如SELECTor)) 作为字符串发送到MySQL服务器INSERT一些API还提供单独的特殊事务提交和回滚函数或方法。

14.5.2.3一致的非锁定读取

一致的读取 该装置InnoDB使用多版本呈现给一个查询数据库的快照在一个时间点。该查询可以查看在该时间点之前提交的事务所做的更改,以及以后或未提交的事务所做的更改。此规则的例外是该查询查看同一事务中较早的语句所做的更改。此异常会导致以下异常:如果更新表中的某些行,请执行下列操作: SELECT看到最新版本的更新行,但它也可能会看到任何行的旧版本。如果其他会话同时更新同一个表,异常意味着您可能会看到该表处于数据库中从未存在的状态。

如果事务 隔离级别REPEATABLE READ(缺省级别),则同一事务中的所有一致读取将读取该事务中第一次读取所创建的快照。您可以通过提交当前事务并在发出新查询之后为您的查询获得更新鲜的快照。

通过READ COMMITTED隔离级别,事务中的每次一致读取都会设置并读取其自己的新快照。

一致的读取是InnoDB进程 SELECT声明 READ COMMITTEDREPEATABLE READ隔离级别的默认模式 一致的读取不会在它访问的表上设置任何锁,因此其他会话可以自由修改这些表,同时在表上执行一致的读取。

假设您正在运行默认的 REPEATABLE READ隔离级别。当您发出一致的读取(即普通 SELECT语句)时, InnoDB会为您的事务提供一个根据您的查询查看数据库的时间点。如果另一个事务删除了一行并在分配了时间点后提交,则不会看到该行已被删除。插入和更新的处理方式相似。

注意

数据库状态的快照适用 SELECT于事务内的语句,不一定适用于 DML语句。如果您插入或修改某些行,然后提交该交易中, DELETEUPDATE从其他并发发出声明REPEATABLE READ 的交易可能会影响到刚刚犯行,即使会议无法对它们进行查询。如果事务更新或删除由不同事务提交的行,则这些更改对当前事务变得可见。例如,您可能会遇到如下情况:

SELECT COUNT(c1)FROM t1 WHERE c1 ='xyz';
- 返回0:没有行匹配。
DELETE FROM t1 WHERE c1 ='xyz';
- 删除其他事务最近提交的几行。

SELECT COUNT(c2)FROM t1 WHERE c2 ='abc';
- 返回0:没有行匹配。
UPDATE t1 SET c2 ='cba'WHERE c2 ='abc';
- 影响10行:另一个txn只提交了10行'abc'值。
SELECT COUNT(c2)FROM t1 WHERE c2 ='cba';
- 返回10:这个txn现在可以看到它刚刚更新的行。

你可以通过提交你的交易来完成你的时间点,然后再做另一个SELECT或者 START TRANSACTION WITH CONSISTENT SNAPSHOT

这称为多版本并发控制

在下面的例子中,只有当B提交了插入并且A已经提交时,会话A才看到由B插入的行,以便时间点超过B的提交。

             会议A会议B

           SET autocommit = 0; SET autocommit = 0;
时间
| SELECT * FROM t;
| 空集
| 插入t值(1,2);
|
v SELECT * FROM t;
           空集
                                  承诺;

           SELECT * FROM t;
           空集

           承诺;

           SELECT * FROM t;
           ---------------------
           | 1 | 2 |
           ---------------------

如果要查看数据库最新状态,请使用READ COMMITTED隔离级别或 锁定读取

SELECT * FROM t FOR SHARE;

通过READ COMMITTED隔离级别,事务中的每次一致读取都会设置并读取其自己的新快照。使用时LOCK IN SHARE MODE,会发生锁定读取:A SELECT阻塞,直到包含最新行的事务结束(请参见 第14.5.2.4节“锁定读取”)。

一致的读取不适用于某些DDL语句:

  • 一致的读取无法完成DROP TABLE,因为MySQL不能使用已经被删除并InnoDB破坏表格的表格。

  • 一致的读取不会结束 ALTER TABLE,因为该语句创建原始表的临时副本,并在构建临时副本时删除原始表。在事务中重新发布一致的读取时,新表中的行不可见,因为在执行事务快照时,这些行不存在。在这种情况下,事务返回错误: ER_TABLE_DEF_CHANGED表定义已更改,请重试事务

读取的类型因条件(例如INSERT INTO ... SELECT,)中的选择而不同 UPDATE ... (SELECT),并且 CREATE TABLE ... SELECT不指定FOR UPDATELOCK IN SHARE MODE

14.5.2.4锁定读取

如果您查询数据,然后在同一个事务中插入或更新相关数据,则常规SELECT 语句不会提供足够的保护。其他事务可以更新或删除刚才查询的相同行。 InnoDB支持两种提供额外安全性锁定读取

  • SELECT ... LOCK IN SHARE MODE

    在读取的任何行上设置共享模式锁定。其他会话可以读取行,但在您的事务提交之前无法修改它们。如果这些行中的任何一行已被另一个尚未提交的事务更改,那么您的查询将一直等到该事务结束,然后使用最新值。

  • SELECT ... FOR UPDATE

    对于搜索遇到的索引记录,锁定行和任何关联的索引条目,就像UPDATE为这些行发布 语句一样。其他事务被阻止更新这些行,不执行SELECT ... LOCK IN SHARE MODE或以某些事务隔离级别读取数据。一致的读取忽略读取视图中存在的记录上设置的任何锁定。(记录的旧版本不能被锁定;它们通过在记录的内存副本上应用撤消日志来重建 。)

这些子句在处理树形结构或图形结构化数据时非常有用,无论是在单个表中还是在多个表中拆分。您可以将边或树枝从一处移到另一处,同时保留返回并更改这些 指针值的权利。

当事务被提交或回滚时, 所有由设置LOCK IN SHARE MODEFOR UPDATE查询设置的锁都会被释放。

注意

SELECT FOR UPDATE仅在自动提交被禁用时(START TRANSACTION或者通过设置autocommit为0 开始事务 或通过设置 为0来 锁定行以进行更新)。如果启用自动提交,则与规范匹配的行不会被锁定。

锁定读取示例

假设你想在表中插入一个新行 child,并确保子行在表中有一个父行parent您的应用程序代码可以确保贯穿这一系列操作的参照完整性。

首先,使用一致的读取来查询表 PARENT并验证父行是否存在。你能安全地将子行插入表中 CHILD吗?不,因为其他会话可能会在您SELECT和您之间的那一刻删除父行 INSERT,而您没有意识到它。

为避免此潜在问题,请执行以下 SELECT操作LOCK IN SHARE MODE

SELECT * FROM parent WHERE NAME ='Jones'锁定共享模式;

在之后LOCK IN SHARE MODE的查询返回父'Jones',你可以放心地将孩子记录添加到CHILD表并提交事务。任何尝试获取PARENT表中适用行的排它锁的事务都会 等待,直到完成为止,也就是说,直到所有表中的数据处于一致状态。

又如,考虑表中的整数计数器字段CHILD_CODES,用于为添加到表的每个子项分配唯一标识符 CHILD不要使用一致性读取或共享模式读取读取计数器的当前值,因为数据库的两个用户可能会看到计数器的相同值,并且如果两个事务尝试添加行,则会出现重复键错误CHILD表格中的标识符相同

在这里,LOCK IN SHARE MODE这不是一个好的解决方案,因为如果两个用户同时读取计数器,当它尝试更新计数器时,至少有一个用户死锁。

要实现读取和递增计数器,首先使用计数器对计数器进行锁定读取FOR UPDATE,然后递增计数器。例如:

SELECT counter_field FROM child_codes FOR UPDATE;
UPDATE child_codes SET counter_field = counter_field + 1;

A SELECT ... FOR UPDATE读取最新的可用数据,在其读取的每一行上设置独占锁。因此,它设置了搜索SQL UPDATE 将在行上设置的相同锁

前面的描述仅仅是一个如何SELECT ... FOR UPDATE工作的例子 在MySQL中,生成唯一标识符的具体任务实际上可以使用对表的单一访问来完成:

UPDATE child_codes SET counter_field = LAST_INSERT_ID(counter_field + 1);
SELECT LAST_INSERT_ID();

SELECT语句仅检索标识符信息(特定于当前连接)。它不访问任何表。

14.5.3在InnoDB中通过不同的SQL语句设置的锁

一个锁定读,一个 UPDATEDELETE一般设置纪录是在SQL语句的处理扫描每个索引记录锁定。WHERE在声明中是否存在会排除该行的条件并不重要 InnoDB不记得确切的WHERE情况,但只知道扫描了哪些索引范围。这些锁通常是下 一个键锁,它也会在记录之前立即阻止插入间隙 ”中但是, 可以显式禁用间隙锁定,这会导致不使用下一个锁定键。有关更多信息,请参阅 第14.5.1节“InnoDB锁定”事务隔离级别还可以影响设置了哪些锁; 请参见 第14.5.2.1节“事务隔离级别”

如果在搜索中使用辅助索引,并且要设置的索引记录锁是独占的,则InnoDB还会检索相应的聚集索引记录并在其上设置锁。

第14.5.1节“InnoDB锁定” 介绍了共享锁和独占锁之间的区别

如果您没有适合您的语句的索引,并且MySQL必须扫描整个表以处理语句,则表的每一行都会被锁定,从而阻止其他用户的所有插入到表中。创建好的索引非常重要,以便您的查询不会不必要地扫描多行。

对于SELECT ... FOR UPDATEor SELECT ... LOCK IN SHARE MODE,锁定是为扫描行获取的,并且对于不符合结果集条件的行(例如,如果它们不符合WHERE条款中给出的条件,将被释放但是,在某些情况下,行可能不会立即解锁,因为在执行查询期间,结果行与其原始源之间的关系会丢失。例如,在一个 UNION,从表中扫描(和锁定)的行可能会在评估之前插入临时表中,以确定它们是否符合结果集。在这种情况下,临时表中的行与原始表中的行之间的关系会丢失,并且后面的行在查询执行结束之前不会解锁。

InnoDB 如下设置特定类型的锁。

  • SELECT ... FROM是一致的读取,读取数据库的快照并设置不锁定,除非事务隔离级别设置为 SERIALIZABLE对于 SERIALIZABLE级别,搜索会在遇到的索引记录上设置共享的下一个键锁。但是,对于使用唯一索引锁定行来搜索唯一行的语句,只需要索引记录锁定。

  • SELECT ... FROM ... LOCK IN SHARE MODE在搜索遇到的所有索引记录上设置共享的下一个键锁定。但是,对于使用唯一索引锁定行来搜索唯一行的语句,只需要索引记录锁定。

  • SELECT ... FROM ... FOR UPDATE在搜索遇到的每个记录上设置唯一的下一个键锁定。但是,对于使用唯一索引锁定行来搜索唯一行的语句,只需要索引记录锁定。

    对于搜索遇到的索引记录, SELECT ... FROM ... FOR UPDATE阻止其他会话执行 SELECT ... FROM ... LOCK IN SHARE MODE或读取某些事务隔离级别。一致的读取忽略读取视图中存在的记录上设置的任何锁定。

  • UPDATE ... WHERE ...在搜索遇到的每个记录上设置唯一的下一个键锁定。但是,对于使用唯一索引锁定行来搜索唯一行的语句,只需要索引记录锁定。

  • UPDATE修改一个聚集索引记录,隐含的锁被采取对受影响的第二个索引记录。UPDATE在插入新的二级索引记录之前执行重复检查扫描时以及插入新的二级索引记录时,操作还会对受影响的二级索引记录执行共享锁定。

  • DELETE FROM ... WHERE ...在搜索遇到的每个记录上设置唯一的下一个键锁定。但是,对于使用唯一索引锁定行来搜索唯一行的语句,只需要索引记录锁定。

  • INSERT在插入的行上设置独占锁。该锁是一个索引记录锁,而不是下一个键锁(即没有间隙锁),并且不会阻止其他会话插入到插入行之前的间隙中。

    在插入行之前,设置一种称为插入意图间隙锁的间隙锁。这个锁定以插入到相同索引间隙中的多个事务不需要等待对方的方式插入的意图,如果它们没有插入间隙中的相同位置。假设有索引记录的值为4和7.尝试插入5和6值的单独事务每个在插入行上获得排它锁之前用插入意向锁锁定4和7之间的间隔,但不要因为行不冲突而彼此阻塞。

    如果发生重复键错误,则会设置重复索引记录上的共享锁。如果另一个会话已具有排他锁,则如果有多个会话尝试插入同一行,则此共享锁的使用可能导致死锁。如果另一个会话删除该行,则会发生这种情况。假设InnoDB表格 t1具有以下结构:

    CREATE TABLE t1(INT,PRIMARY KEY(i))ENGINE = InnoDB;
    

    现在假设三个会话按顺序执行以下操作:

    第一部分:

    开始交易;
    INSERT INTO t1 VALUES(1);
    

    会议2:

    开始交易;
    INSERT INTO t1 VALUES(1);
    

    第三场:

    开始交易;
    INSERT INTO t1 VALUES(1);
    

    第一部分:

    ROLLBACK;
    

    会话1的第一个操作获取该行的排它锁。会话2和3的操作都会导致重复键错误,并且它们都会为该行请求共享锁。当会话1回滚时,它将释放对该行的排它锁,并为会话2和3授予排队的共享锁请求。此时,会话2和3发生死锁:因为另一方持有共享锁,所以都不能获得该行的排它锁。

    如果表中已经包含具有键值1的行并且三个会话按顺序执行以下操作,则会出现类似的情况:

    第一部分:

    开始交易;
    DELETE FROM t1 WHERE i = 1;
    

    会议2:

    开始交易;
    INSERT INTO t1 VALUES(1);
    

    第三场:

    开始交易;
    INSERT INTO t1 VALUES(1);
    

    第一部分:

    承诺;
    

    会话1的第一个操作获取该行的排它锁。会话2和3的操作都会导致重复键错误,并且它们都会为该行请求共享锁。当会话1提交时,它将释放对该行的排它锁,并为会话2和3授予排队的共享锁请求。此时,会话2和3发生死锁:由于另一方持有共享锁,因此无法获得该行的排它锁。

  • INSERT ... ON DUPLICATE KEY UPDATE不同之处在于 INSERT当发生重复密钥错误时,在要更新的行上放置排他锁而不是共享锁。对重复的主键值采取独占索引记录锁定。独占的下一个键锁定用于重复的唯一键值。

  • REPLACE就像INSERT一个独特的密钥没有碰撞一样完成 否则,在要替换的行上放置专有的下一个键锁定。

  • INSERT INTO T SELECT ... FROM S WHERE ... 在插入的每一行上设置独占索引记录锁(无间隙锁)T如果事务隔离级别为READ COMMITTEDinnodb_locks_unsafe_for_binlog 已启用且事务隔离级别不是 SERIALIZABLEInnoDB那么S作为一致性读取进行搜索 (不锁定)。否则,InnoDB在行上设置共享的下一个键锁SInnoDB必须在后一种情况下设置锁定:在从备份中前滚恢复时,每个SQL语句必须以与原来完成的方式完全相同的方式执行。

    CREATE TABLE ... SELECT ...执行 SELECT与共享的下一个键锁定或作为一致的读取,如 INSERT ... SELECT

    SELECT在构建中使用 REPLACE INTO t SELECT ... FROM s WHERE ...UPDATE t ... WHERE col IN (SELECT ... FROM s ...)InnoDB集共享来自表中的行的下键锁s

  • 在初始化AUTO_INCREMENT表中先前指定的 列的同时,在 InnoDB与该AUTO_INCREMENT关联的索引的末尾设置排它锁 在访问自动增量计数器时,InnoDB使用特定的AUTO-INC表锁定模式,其中锁只持续到当前SQL语句的末尾,而不是整个事务的末尾。其他会话在AUTO-INC 表锁被保持时不能插入到表中; 请参见 第14.5.2节“InnoDB事务模型”

    InnoDBAUTO_INCREMENT不设置任何锁的情况下获取先前初始化的的值

  • 如果FOREIGN KEY在表上定义了一个约束,那么需要检查约束条件的任何插入,更新或删除都会在它检查约束的记录上设置共享记录级锁。 InnoDB还会在约束失败的情况下设置这些锁。

  • LOCK TABLES设置表锁,但它是InnoDB设置这些锁的图层上面的较高MySQL层 InnoDB如果 innodb_table_locks = 1(默认)以及 autocommit = 0上面的MySQL层InnoDB知道行级锁,就知道表锁。

    否则,InnoDB在涉及这种表锁的情况下,自动死锁检测无法检测到死锁。另外,因为在这种情况下,较高的MySQL层不知道行级别锁定,所以可以在另一个会话当前具有行级别锁定的表上获得表锁定。但是,这不会危及事务完整性,如 第14.5.5.2节“死锁检测和回滚”中所述另请参见 第14.8.1.7节“InnoDB表的限制”

14.5.4幻影行

当相同的查询在不同时间产生不同组的行时, 所谓的幻影问题发生在事务中。例如,如果a SELECT被执行了两次,但第二次返回的是第一次未返回的行,则该行是幻影行。

假设id上有一个索引,child并且您希望读取并锁定标识符值大于100的表中的所有行,并打算稍后更新所选行中的某一列:

SELECT * FROM child WHERE id> 100 FOR UPDATE;

查询从id大于100 的第一条记录开始扫描索引 。让该表包含id值为90和102的行。如果在扫描范围内的索引记录上设置的锁不锁定在间隙中进行的插入在这种情况下,90和102之间的差距),另一个会话可以id在101 的表中插入一个新行 。如果要在同SELECT一个事务中执行 相同的事务,则会看到一个id101 行的新行(一个 幻影)在查询返回的结果集中。如果我们将一组行视为一个数据项,那么新的幻像子将违反事务应该能够运行的事务的隔离原则,以便在事务处理期间它所读取的数据不会改变。

为了防止幻像,InnoDB使用称为下一个键锁定的算法该算法结合了索引行锁定和间隙锁定。 InnoDB以这样的方式执行行级锁定,即当它搜索或扫描表索引时,它会在遇到的索引记录上设置共享锁或排它锁。因此,行级锁实际上是索引记录锁。另外,索引记录上的下一个键锁也会影响该索引记录之前间隙也就是说,下一个键锁定是索引记录锁定,并在索引记录之前的间隔上加上间隙锁定。如果一个会话有记录的共享或排他锁R在索引中,另一个会话不能R在索引顺序中立即在间隙中插入新的索引记录

InnoDB扫描索引,它也可以锁定在指数的最后一个记录之后的间隙。在前面的例子中,就发生了这种情况:为了防止在表中插入 id大于100的任何数据,设置 InnoDB的锁在id值102之后的间隙中包含一个锁

您可以使用下一个键锁定在您的应用程序中实现唯一性检查:如果您以共享模式读取数据,并且没有看到要插入的行的重复项,那么您可以安全地插入行并知道在读取过程中设置在行的后继键上的下一个键锁可以防止任何人同时为行插入副本。因此,下一个键锁定使您能够锁定表中不存在的东西。

可以禁用间隙锁定,如 第14.5.1节“InnoDB锁定”中所述这可能会导致幻影问题,因为当禁用间隙锁定时,其他会话可以将新行插入到间隙中。

14.5.5 InnoDB中的死锁

死锁是由于每个事务持有另一个需要的锁而导致不同事务无法继续的情况。因为两个事务都在等待资源变为可用,所以既不释放它拥有的锁。

当事务锁定多个表中的行时(通过诸如UPDATE或的 语句SELECT ... FOR UPDATE),可能会发生死锁 ,但顺序相反。当这些语句锁定索引记录和间隔的范围时,也会发生死锁,每个事务由于计时问题而获取一些锁而不是其他锁。有关死锁示例,请参见 第14.5.5.1节“InnoDB死锁示例”

为了减少死锁的可能性,使用事务而不是LOCK TABLES语句; 保持插入或更新数据的事务足够小以至于不能长时间保持打开状态; 当不同的事务更新多个表或大范围的行时,请SELECT ... FOR UPDATE在每个事务中使用相同的操作顺序(例如 ); SELECT ... FOR UPDATEUPDATE ... WHERE 语句中使用的列上创建索引死锁的可能性不受隔离级别的影响,因为隔离级别改变了读操作的行为,而死锁因为写操作而发生。有关避免和从死锁状态恢复的更多信息,请参阅 第14.5.5.3节“如何最小化和处理死锁”

当启用死锁检测(默认)并发生死锁时,InnoDB检测条件并回滚其中一个事务(受害者)。如果使用innodb_deadlock_detect 配置选项禁用死锁检测 ,则InnoDB依赖该 innodb_lock_wait_timeout设置来回滚死锁情况下的事务。因此,即使您的应用程序逻辑正确,您仍然必须处理必须重试事务的情况。要查看InnoDB用户事务中的最后一个死锁,请使用该 SHOW ENGINE INNODB STATUS命令。如果频繁死锁突出显示事务结构或应用程序错误处理的问题,请使用 innodb_print_all_deadlocks 设置启用将有关所有死锁的信息打印到 mysqld错误日志中。有关死锁如何自动检测和处理的更多信息,请参见 第14.5.5.2节“死锁检测和回滚”

14.5.5.1 InnoDB死锁示例

以下示例说明了锁请求会导致死锁时如何发生错误。这个例子涉及两个客户,A和B.

首先,客户端A创建一个包含一行的表,然后开始一个事务。在事务中,A通过S在共享模式中选择它来获得 行上的锁定:

MySQL的> CREATE TABLE t (i INT) ENGINE = InnoDB;
查询OK,0行受影响(1.07秒)

MySQL的> INSERT INTO t (i) VALUES(1);
查询OK,1行受影响(0.09秒)

MySQL的> START TRANSACTION;
查询OK,0行受影响(0.00秒)

MySQL的> SELECT * FROM t WHERE i = 1 LOCK IN SHARE MODE;
+ ------ +
| 我|
+ ------ +
| 1 |
+ ------ +

接下来,客户端B开始一个事务并尝试从表中删除该行:

MySQL的> START TRANSACTION;
查询OK,0行受影响(0.00秒)

MySQL的> DELETE FROM t WHERE i = 1;

删除操作需要X 锁定。该锁不能被授予,因为它与S客户端A持有不兼容,所以该请求会进入行和客户端B块的锁请求队列。

最后,客户端A也尝试从表中删除该行:

MySQL的> DELETE FROM t WHERE i = 1;
错误1213(40001):尝试获取锁定时发现死锁;
尝试重新启动事务

死锁发生在这里,因为客户端A需要一个 X锁来删除该行。但是,该锁定请求不能被授予,因为客户端B已经有一个X锁定请求并且正在等待客户端A释放其S 锁定。由于B事先请求锁定,因此SA持有也不能升级XX锁。因此,InnoDB为其中一个客户端生成错误并释放其锁。客户返回这个错误:

错误1213(40001):尝试获取锁定时发现死锁;
尝试重新启动事务

此时,可以授予其他客户端的锁定请求,并从表中删除该行。

14.5.5.2死锁检测和回滚

启用死锁检测(默认)时,会 InnoDB自动检测事务 死锁并回退一个或多个事务来打破死锁。 InnoDB尝试选择小事务回滚,其中事务的大小由插入,更新或删除的行数确定。

InnoDB知道表锁如果 innodb_table_locks = 1(默认) autocommit = 0,并且上层的MySQL层知道行级锁。否则, InnoDB无法检测由MySQL LOCK TABLES 语句设置的表锁或由InnoDB涉及的其他存储引擎设置的锁的死锁 通过设置innodb_lock_wait_timeout系统变量的值来解决这些情况

InnoDB执行事务的完整回滚时,释放由事务设置的所有锁。但是,如果只有一条SQL语句由于错误而回滚,则该语句设置的某些锁可能会被保留。发生这种情况是因为InnoDB 存储行格式的锁定的格式使得它无法知道哪个锁由哪个语句设置。

如果SELECT在事务中调用存储的函数,并且函数中的语句失败,那么该语句会回滚。而且,如果 ROLLBACK在此之后执行,则整个事务回滚。

如果LATEST DETECTED DEADLOCKInnoDB监视器输出包括一条消息指出,过深或长时间的搜寻锁表WAITS-FOR图中,我们将回滚下面的事务这表明交易的所述等待名单上的人数已经达到了限制为200.超过200个事务的等待列表被视为死锁,并且试图检查等待列表的事务将被回滚。如果锁定线程必须查看等待列表上的事务拥有的超过1,000,000个锁,则也会发生同样的错误。

有关组织数据库操作以避免死锁的技术,请参见第14.5.5节“InnoDB中的死锁”

禁用死锁检测

在高并发系统上,当大量线程等待相同的锁时,死锁检测会导致速度下降。有时候,innodb_lock_wait_timeout 当死锁发生时,禁用死锁检测并依赖事务回滚设置可能更有效 使用innodb_deadlock_detect 配置选项可以禁用死锁检测

14.5.5.3如何最小化和处理死锁

本节基于第14.5.5.2节“死锁检测和回滚”中关于死锁的概念信息它解释了如何组织数据库操作以最大限度地减少死锁以及应用程序中所需的后续错误处理。

死锁是交易数据库中的一个典型问题,但它们并不危险,除非它们频繁发生,根本无法运行某些事务。通常,您必须编写应用程序,以便它们随时准备重新发出一个事务,如果它由于死锁而回滚。

InnoDB使用自动行级锁定。即使在插入或删除单行的事务中,也可能会出现死锁。那是因为这些行动并非真正的原子他们自动在插入或删除的行的索引记录(可能有几个)上设置锁定。

您可以通过以下技术来应对死锁并减少它们发生的可能性:

  • 在任何时候,发出该 SHOW ENGINE INNODB STATUS命令以确定最近发生的死锁的原因。这可以帮助您调整应用程序以避免死锁。

  • 如果经常出现死锁警告,请通过启用innodb_print_all_deadlocks 配置选项收集更多的调试信息 关于每个死锁的信息,不仅仅是最新的,记录在MySQL 错误日志中完成调试后禁用此选项。

  • 如果事务由于死锁而失败,请始终准备重新发出事务。僵局并不危险。再试一次。

  • 保持交易持续时间较短,以减少冲突。

  • 在进行一系列相关更改后立即提交事务,以减少冲突。特别是,不要让交互式 mysql会话在未提交事务的情况下长时间处于打开状态。

  • 如果使用锁定读取SELECT ... FOR UPDATESELECT ... LOCK IN SHARE MODE),请尝试使用较低的隔离级别,例如 READ COMMITTED

  • 在事务中修改多个表或同一表中的不同行时,每次都要以一致的顺序执行这些操作。然后事务形成明确定义的队列并且不会发生死锁。例如,组织数据库操作到功能在应用程序中,或调用存储程序,而不是编码的多个相似序列 INSERTUPDATE以及 DELETE在不同的地方语句。

  • 将精心挑选的索引添加到表格中。然后,您的查询需要扫描更少的索引记录,从而设置更少的锁。使用EXPLAIN SELECT以确定哪些索引MySQL认为最适合您的查询。

  • 使用更少的锁定。如果您可以承诺允许 SELECT从旧快照返回数据,请不要添加该子句FOR UPDATE添加该子句LOCK IN SHARE MODEREAD COMMITTED这里使用隔离级别是很好的,因为在同一事务中每次一致的读取都会从它自己的新快照中读取。

  • 如果没有其他帮助,请使用表级锁定序列化您的事务。LOCK TABLES与事务表(如InnoDB 表)一起使用的正确方法是使用 SET autocommit = 0(not START TRANSACTION开头事务LOCK TABLES,并且UNLOCK TABLES在显式提交事务之前不要调用 例如,如果您需要写入表格 t1并从表格中读取 t2,则可以这样做:

    SET autocommit = 0;
    锁定表t1写,t2读,...;
    ... do something with tables t1 and t2 here ...
    承诺;
    解锁表;
    

    表级锁定可防止对表进行并发更新,从而避免死锁,但会降低对繁忙系统的响应速度。

  • 序列化事务的另一种方法是创建一个仅包含单行的辅助信号量表。在访问其他表之前,让每个事务更新该行。这样,所有的交易都是以串行的方式进行的。请注意,InnoDB 即时死锁检测算法也适用于这种情况,因为序列化锁是行级锁。使用MySQL表级锁定时,必须使用超时方法来解决死锁问题。

14.6 InnoDB配置

本节提供有关存储引擎的InnoDB初始化,启动以及各种组件和功能的配置信息和过程 InnoDB有关优化InnoDB表的数据库操作的信息 ,请参见 第8.5节“优化InnoDB表”

14.6.1 InnoDB启动配置

关于InnoDB 配置的第一个决定涉及数据文件,日志文件,页面大小和内存缓冲区的配置。建议您在创建InnoDB实例之前定义数据文件,日志文件和页面大小配置InnoDB创建实例后修改数据文件或日志文件配置可能涉及一个非平凡的过程,并且页面大小只能在InnoDB实例初次初始化时定义

除这些主题外,本节还提供有关指定InnoDB配置文件中的选项,查看InnoDB 初始化信息以及重要的存储注意事项的信息。

在MySQL配置文件中指定选项

由于MySQL使用数据文件,日志文件和页面大小配置设置来初始化 InnoDB实例,因此建议您InnoDB在初次启动之前在启动时读取的配置文件中定义这些设置InnoDB在MySQL服务器启动时初始化,第一次初始化 InnoDB通常在第一次启动MySQL服务器时发生。

您可以将InnoDB选项放置[mysqld]服务器启动时读取的任何选项文件组中。MySQL选项文件的位置在第4.2.6节“使用选项文件”中介绍

要确保mysqld仅从特定文件读取选项,请--defaults-file在启动服务器时使用该 选项作为命令行中的第一个选项:

mysqld --defaults-file =path_to_configuration_file

查看InnoDB初始化信息

InnoDB在启动过程中查看初始化信息,请从命令提示符处启动mysqld从命令提示符启动mysqld时,初始化信息将打印到控制台。

例如,在Windows上,如果mysqld位于C:\Program Files\MySQL\MySQL Server 5.7\bin,请启动MySQL服务器,如下所示:

C:\> "C:\Program Files\MySQL\MySQL Server 5.7\bin\mysqld" --console

在类Unix系统上,mysqld位于binMySQL安装目录中:

外壳> bin/mysqld --user=mysql &

如果您没有将服务器输出发送到控制台,请在启动后检查错误日志以查看InnoDB在启动过程中打印的初始化信息

有关使用其他方法启动MySQL的信息,请参见 第2.10.5节“自动启动和停止MySQL”

注意

InnoDB在启动时不打开所有用户表和关联的数据文件。但是, InnoDB它会检查*.ibd数据字典中引用的表空间文件(文件)的存在如果找不到表空间文件,则InnoDB记录错误并继续启动顺序。重做日志中引用的表空间文件可能在重做应用程序的崩溃恢复期间打开。

重要的存储注意事项

继续进行启动配置之前,请查看以下与存储相关的注意事项。

  • 在某些情况下,如果数据未全部放置在同一物理磁盘上,数据库性能会提高。将日志文件放在与数据不同的磁盘上通常对性能有利。例如,您可以将系统表空间数据文件和日志文件放在不同的磁盘上。您还可以将原始磁盘分区(原始设备)用于 InnoDB数据文件,这可能会加速I / O。请参见第14.7.3节“为系统表空间使用原始磁盘分区”

  • InnoDB是MySQL的事务安全(ACID兼容)存储引擎,具有提交,回滚和崩溃恢复功能来保护用户数据。但是,如果底层操作系统或硬件不能像宣传的那样工作,则不能这样做许多操作系统或磁盘子系统可能会延迟或重新排序写入操作以提高性能。在一些操作系统上,非常 fsync()系统调用应该等到文件的所有未写入数据已被刷新后,实际上可能会在数据刷新到稳定存储之前返回。因此,操作系统崩溃或停电可能会破坏最近提交的数据,或者在最糟糕的情况下,由于写入操作被重新排序,甚至会损坏数据库。如果数据完整性对您很重要,请 在生产中使用任何内容之前执行一些拔插测试。在OS X 10.3及更高版本上,InnoDB使用特殊的 fcntl()文件冲洗方法。在Linux下,建议禁用写回缓存

    在ATA / SATA磁盘驱动器上,这样的命令hdparm -W0 /dev/hda可能会禁用写回缓存。 请注意,某些驱动器或磁盘控制器可能无法禁用写回缓存。

  • 关于InnoDB保护用户数据的恢复功能, InnoDB使用涉及称为双写缓冲区的结构的文件刷新技术,该结构 默认为启用(innodb_doublewrite=ON)。双重写入缓冲区增加了崩溃或断电后恢复的安全性,并通过减少fsync()操作需求提高了大多数Unix系统的性能 innodb_doublewrite 如果您关心数据完整性或可能的故障,建议您保持启用选项。有关doublewrite缓冲区的更多信息,请参阅 第14.12.1节“InnoDB磁盘I / O”

  • 在使用NFS之前InnoDB,请查看使用NFS与MySQL中概述的潜在问题

  • 在Windows上的4K扇区硬盘上运行MySQL服务器不支持 innodb_flush_method=async_unbuffered,这是默认设置。解决方法是使用 innodb_flush_method=normal

系统表空间数据文件配置

innodb_data_file_path 配置选项定义的名称,大小,和属性 InnoDB系统表空间的数据文件。如果您未指定值 innodb_data_file_path,则默认行为是创建一个自动扩展数据文件,该文件略大于12MB,即已命名ibdata1

要指定多个数据文件,请用分号(;)字符分隔它们

innodb_data_file_path = datafile_spec1[; datafile_spec2] ...

以下设置配置了一个名为“ ibdata1自动扩展” 的单个12MB数据文件 没有给出文件的位置,所以默认情况下,InnoDB 在MySQL数据目录中创建它:

的[mysqld]
innodb_data_file_path中= ibdata1中:12M:自动扩展

文件大小使用KMG后缀字母指定以指示KB,MB或GB的单位。如果以千字节(KB)为单位指定数据文件大小,请以1024的倍数进行此操作。否则,将KB值四舍五入为最接近兆字节(MB)的边界。文件大小的总和必须至少略大于12MB。

为第一个系统表空间数据文件强制执行最小文件大小, 以确保有足够的空间存储双倍缓冲页面:

可以像这样配置ibdata1一个 名为固定大小的50MB数据文件和一个50MB自动扩展文件的系统表空间 ibdata2

的[mysqld]
innodb_data_file_path中= ibdata1中:50M; ibdata2:50M:自动扩展

一个数据文件规范完整的语法包括文件名,文件大小,以及可选的autoextendmax属性:

file_namefile_size[:autoextend [:max:max_file_size]]

autoextendmax 属性只能用于将最后一个指定的数据文件中使用 innodb_data_file_path的设置。

如果您autoextend为最后一个数据文件指定了选项,那么InnoDB扩展数据文件(如果它在表空间中的空闲空间不足)。autoextend增量是在默认情况下,时间64MB。要修改增量,请更改 innodb_autoextend_increment 系统变量。

如果磁盘已满,则可能需要在另一个磁盘上添加另一个数据文件。有关说明,请参见 第14.7.1节“调整InnoDB系统表空间的大小”

单个文件的大小限制取决于您的操作系统。在支持大文件的操作系统上,您可以将文件大小设置为4GB以上。您还可以 使用原始磁盘分区作为数据文件

InnoDB不知道文件系统的最大文件大小,因此请谨慎处理最大文件大小为2GB等较小值的文件系统。要指定自动扩展数据文件的最大大小,请使用 max属性后面的 autoextend属性。max仅在限制磁盘使用率至关重要的情况下使用该 属性,因为超过最大大小会导致致命错误,可能导致服务器退出。以下配置允许 ibdata1增长到500MB的限制:

的[mysqld]
innodb_data_file_path中= ibdata1中:12M:自动扩展:最大:500M

InnoDB默认情况下(datadir,在MySQL数据目录中创建系统表空间文件要明确指定位置,请使用该 innodb_data_home_dir选项。例如,要在名为的目录中创建两个名为的文件 ibdata1,请ibdata2如下所示进行myibdata配置 InnoDB

的[mysqld]
innodb_data_home_dir = / path / to / myibdata /
innodb_data_file_path中= ibdata1中:50M; ibdata2:50M:自动扩展
注意

指定值时需要尾部斜线 innodb_data_home_dir

InnoDB不会创建目录,因此myibdata在启动服务器之前请确保目录存在。使用Unix或DOS mkdir命令创建目录。

确保MySQL服务器具有在数据目录中创建文件的正确访问权限。更一般地说,服务器必须在任何需要创建数据文件的目录中拥有访问权限。

InnoDB通过将数值文件连接innodb_data_home_dir到数据文件名称来形成每个数据文件的目录路径 如果innodb_data_home_dir未指定选项,则默认值为dot 目录./,这表示MySQL数据目录。(MySQL服务器在开始执行时将其当前工作目录更改为其数据目录。)

如果您指定 innodb_data_home_dir为空字符串,则可以为innodb_data_file_path值中列出的数据文件指定绝对路径 以下示例等同于上述示例:

的[mysqld]
innodb_data_home_dir =
innodb_data_file_path中= /路径/到/ myibdata / ibdata1中:50M; /路径/到/ myibdata / ibdata2:50M:自动扩展

InnoDB日志文件配置

默认情况下,InnoDB在MySQL数据目录(datadir)中创建两个48MB的日志文件named ib_logfile0ib_logfile1

以下选项可用于修改默认配置:

  • innodb_log_group_home_dir 定义InnoDB日志文件的目录路径(重做日志)。如果未配置此选项, InnoDB则会在MySQL数据目录(datadir中创建日志文件

    您可以使用此选项将InnoDB 日志文件放置在与InnoDB数据文件不同的物理存储位置, 以避免潜在的I / O资源冲突。例如:

    的[mysqld]
    innodb_log_group_home_dir = / dr3 / iblogs
    
    注意

    InnoDB不会创建目录,因此在启动服务器之前请确保日志目录存在。使用Unix或DOS mkdir 命令创建任何必需的目录。

    确保MySQL服务器具有在日志目录中创建文件的正确访问权限。更一般地说,服务器必须在任何需要创建日志文件的目录中拥有访问权限。

  • innodb_log_files_in_group 定义日志组中的日志文件数量。默认值和推荐值是2。

  • innodb_log_file_size 定义日志组中每个日志文件的字节大小。日志文件的组合大小(innodb_log_file_size* innodb_log_files_in_group)不能超过略小于512GB的最大值。例如,一对255 GB的日志文件接近极限,但不超过它。默认的日志文件大小为48MB。通常,日志文件的组合大小应该足够大,以便服务器可以消除工作负载活动中的高峰和低谷,这通常意味着有足够的重做日志空间来处理一个多小时的写入活动。值越大,缓冲池中所需的检查点刷新活动就越少,从而节省磁盘I / O。有关更多信息,请参见 第8.5.4节“优化InnoDB重做日志记录”

InnoDB撤销表空间配置

默认情况下,InnoDB撤消日志是系统表空间的一部分。但是,您可以选择将InnoDB撤消日志存储 在一个或多个单独的撤消表空间中,通常位于不同的存储设备上。

innodb_undo_directory 配置选项定义了路径 InnoDB创建撤消日志分开的表空间。此选项通常与innodb_rollback_segmentsinnodb_undo_tablespaces 选项一起使用 ,这些选项决定了系统表空间外的撤销日志的磁盘布局。

注意

innodb_undo_tablespaces 已弃用,将在未来版本中删除。

有关更多信息,请参见 部分14.7.7,“配置撤消表空间”

InnoDB临时表空间配置

默认情况下,InnoDB创建一个名为的自动扩展临时表空间数据文件ibtmp1,该文件 innodb_data_home_dir 目录中略大于12MB 使用innodb_temp_data_file_path 配置选项可以在启动时修改默认的临时表空间数据文件配置

innodb_temp_data_file_path 选项指定InnoDB临时表空间数据文件的路径,文件名和文件大小 文件的完整目录路径通过连接innodb_data_home_dir到指定的路径 形成 innodb_temp_data_file_path通过将K,M或G附加到大小值中指定文件大小,以KB,MB或GB(1024MB)表示。文件大小的总和必须略大于12MB。

innodb_data_home_dir 默认值是MySQL数据目录(datadir)。

InnoDB页面大小配置

innodb_page_size选项指定InnoDB MySQL实例中所有表空间的页面大小该值在创建实例时设置,并在此后保持不变。有效值为64k,32k,16k(默认值),8k和4k。或者,您可以以字节为单位指定页面大小(65536,32768,16384,8192,4096)。

16k的默认页面大小适用于各种工作负载,特别是涉及涉及批量更新的表扫描和DML操作的查询。对于涉及许多小写入的OLTP工作负载,较小的页面大小可能更有效,当单个页面包含多行时,争用可能成为问题。较小的页面对于SSD存储设备也可能是有效的,SSD存储设备通常使用小块大小。保持InnoDB页面大小接近存储设备块大小可将重写到磁盘的未更改数据量减至最少。

InnoDB内存配置

MySQL为各种缓存和缓冲区分配内存以提高数据库操作的性能。在分配内存时 InnoDB,请始终考虑操作系统所需的内存,分配给其他应用程序的内存以及分配给其他MySQL缓冲区和缓存的内存。例如,如果您使用MyISAM表格,请考虑为键缓冲区(key_buffer_size分配的内存量有关MySQL缓冲区和缓存的概述,请参见 第8.12.4.1节“MySQL如何使用内存”

特定的缓冲区InnoDB使用以下参数进行配置:

警告

在32位GNU / Linux x86上,请注意不要将内存使用设置得太高。glibc可能会允许进程堆扩展到线程堆栈,这会导致服务器崩溃。分配给 全局和每线程缓冲区和缓存mysqld进程的内存接近或超过2GB 是一种风险

用于计算MySQL的全局和每线程内存分配的类似以下公式可用于估计MySQL内存使用情况。您可能需要修改公式来考虑MySQL版本和配置中的缓冲区和缓存。有关MySQL缓冲区和缓存的概述,请参见第8.12.4.1节“MySQL如何使用内存”

innodb_buffer_pool_size
+ key_buffer_size
+ max_connections *(sort_buffer_size + read_buffer_size + binlog_cache_size)
+ max_connections * 2MB

每个线程使用一个堆栈(通常是2MB,但在Oracle公司提供的MySQL二进制文件中只有256KB),最坏的情况下也使用sort_buffer_size + read_buffer_size额外的内存。

在Linux上,如果内核启用了大页面支持,则 InnoDB可以使用大页面为其缓冲池分配内存。请参见第8.12.4.2节“启用大页面支持”

14.6.2将InnoDB配置为只读操作

您现在可以InnoDB通过--innodb-read-only在服务器启动时启用配置选项来查询MySQL数据目录位于只读介质上的表

如何启用

要为只读操作准备实例,请确保在 将数据文件存储在只读介质之前将所有必要信息刷新到数据文件。使用更改缓冲禁用(innodb_change_buffering=0运行服务器并执行缓慢关机

要为整个MySQL实例启用只读模式,请在服务器启动时指定以下配置选项:

  • --innodb-read-only=1

  • 如果该实例位于只读介质(例如DVD或CD)上,或该/var目录不可写入所有: --pid-file=path_on_writeable_media--event-scheduler=disabled

  • --innodb_temp_data_file_path该选项指定InnoDB临时表空间数据文件的路径,文件名和文件大小 默认设置是ibtmp1:12M:autoextend,它ibtmp1在数据目录中创建临时表空间数据文件。要为只读操作准备实例,请将其设置 innodb_temp_data_file_path为数据目录之外的位置。路径必须相对于数据目录; 例如:

    --innodb_temp_data_file_path = .. / .. / .. / TMP / ibtmp1:12M:自动扩展         
    

使用方案

这种操作模式适用于以下情况:

  • 在只读存储介质(如DVD或CD)上分发MySQL应用程序或一组MySQL数据。

  • 多个MySQL实例同时查询同一个数据目录,通常在数据仓库配置中。您可以使用这种技术来避免 可能发生的负载较重的MySQL实例的瓶颈问题,也可以使用不同的配置选项来针对各种实例调整每种查询的特定类型的查询。

  • 由于安全或数据完整性原因(例如归档备份数据),查询已进入只读状态的数据。

注意

此功能主要用于分发和部署的灵活性,而不是基于只读方面的原始性能。有关调整只读查询性能的方法,请参见 第8.5.3节“优化InnoDB只读事务”,该方法不需要使整个服务器只读。

怎么运行的

当服务器通过--innodb-read-only选项以只读模式运行时 ,某些InnoDB功能和组件将被完全减少或关闭:

  • 没有改变缓冲完成,特别是没有从更改缓冲区合并。为了确保在为只读操作准备实例时更改缓冲区为空,请禁用更改缓冲(innodb_change_buffering=0)并首先执行缓慢关闭

  • 启动时 没有崩溃恢复阶段。实例必须在进入只读状态之前执行缓慢关闭

  • 由于重做日志未用于只读操作,innodb_log_file_size因此在将实例设置为只读之前,可以将其设置 为尽可能最小的大小(1 MB)。

  • 除I / O读取线程之外的所有后台线程均被关闭。因此,只读实例不会遇到任何死锁

  • 有关死锁,监视器输出等的信息不会写入临时文件。因此, SHOW ENGINE INNODB STATUS不会产生任何输出。

  • 如果MySQL服务器已启动, --innodb-read-only但数据目录仍在可写介质上,则root用户仍可执行DCL操作,例如GRANTREVOKE

  • 当服务器处于只读模式时,对通常会更改写入操作行为的配置选项设置的更改不起作用。

  • 关闭执行隔离级别MVCC处理所有查询都读取最新版本的记录,因为更新和删除是不可能的。

  • 撤消日志不被使用。禁用innodb_undo_tablespacesinnodb_undo_directory 配置选项的任何设置

14.6.3 InnoDB缓冲池配置

本节提供InnoDB缓冲池的配置和调优信息

14.6.3.1 InnoDB缓冲池

InnoDB维护一个称为缓冲池的存储区域, 用于在内存中缓存数据和索引。了解InnoDB缓冲池如何 工作,并利用它来将频繁访问的数据保存在内存中,这是MySQL调优的一个重要方面。有关InnoDB缓冲池如何工作的信息,请参阅 InnoDB缓冲池LRU算法

您可以配置InnoDB缓冲池的各个方面 以提高性能。

InnoDB缓冲池LRU算法

InnoDB使用最近最少使用(LRU)算法的变体将缓冲池作为列表来管理。当需要空间将新页面添加到池中时,会 InnoDB清除最近最少使用的页面,并将新页面添加到列表的中间。这种 中点插入策略将列表视为两个子列表:

  • 头部是最近访问(或 年轻)页面的子列表

  • 尾部是最近访问过页面的子列表

该算法保留了新子列表中查询大量使用的页面。旧的子列表包含较少使用的页面; 这些网页是驱逐的候选人

LRU算法默认运行如下:

  • 3/8的缓冲池专用于旧的子列表。

  • 列表的中点是新子列表的尾部与旧子列表的头部相交的边界。

  • InnoDB将页面读入缓冲池时,它最初将其插入到中点(旧子列表的头部)。可以读入页面,因为它是用户指定的操作(例如SQL查询)所必需的,或者作为 自动执行的预读操作的 一部分 InnoDB

  • 在旧的子列表中访问一个页面会使其变得 年轻,将其移动到缓冲池的头部(新子列表的头部)。如果页面因为需要而被读入,则第一次访问立即发生并且页面变得年轻。如果由于预读而导致页面被读入,则第一次访问不会立即发生(并且在页面被逐出之前可能根本不会发生)。

  • 随着数据库的运行,在缓冲池的页面没有被访问的年龄通过向列表的尾部移动。新的和旧的子列表中的页面随着其他页面的变化而变旧。在中点插入页面时,旧子列表中的页面也会变老。最终,一段长时间未使用的页面会到达旧的子列表的尾部并被驱逐。

默认情况下,查询读取的页面会立即移动到新的子列表中,这意味着它们会留在缓冲池中的时间更长。表扫描(例如为mysqldump操作执行,或者 执行 SELECT不带 WHERE子句的语句)可以将大量数据带入缓冲池并驱逐相当数量的旧数据,即使新数据从不再使用。同样,由预读后台线程加载,然后只访问一次的页面移动到新列表的头部。这些情况可能会将经常使用的页面推送到旧的子列表中,他们可能会受到驱逐。有关优化此行为的信息,请参阅 第14.6.3.4节“使缓冲池抗扫描”第14.6.3.5节“配置InnoDB缓冲池预取(预读)”

InnoDB标准监视器输出包含BUFFER POOL AND MEMORY与缓冲池LRU算法的操作有关部分中的几个字段有关详细信息,请参见 第14.6.3.9节“使用InnoDB标准监视器监视缓冲池”

InnoDB缓冲池配置选项

几个配置选项影响InnoDB缓冲池的不同方面

14.6.3.2配置InnoDB缓冲池大小

您可以InnoDB在服务器运行时配置缓冲池大小(在启动时)或联机。本节中描述的行为适用于这两种方法。有关在线配置缓冲池大小的更多信息,请参阅在线配置InnoDB缓冲池大小

在增加或减少时 innodb_buffer_pool_size,操作以块为单位执行。块大小由innodb_buffer_pool_chunk_size 配置选项定义,该 选项默认为 128M有关更多信息,请参阅 配置InnoDB缓冲池块大小

缓冲池大小必须始终等于或innodb_buffer_pool_chunk_size* 的倍数 innodb_buffer_pool_instances如果配置innodb_buffer_pool_size的值不等于或等于innodb_buffer_pool_chunk_size* 的倍数, 则将 innodb_buffer_pool_instances缓冲池大小自动调整为等于或 不小于指定缓冲池大小innodb_buffer_pool_chunk_size* 的倍数 innodb_buffer_pool_instances

在以下示例中, innodb_buffer_pool_size设置为8Ginnodb_buffer_pool_instances设置为16innodb_buffer_pool_chunk_size128M,这是默认值。

8G是一个有效的 innodb_buffer_pool_size值,因为它是 * 8G的倍数 ,也就是innodb_buffer_pool_instances=16innodb_buffer_pool_chunk_size=128M2G

外壳> mysqld --innodb_buffer_pool_size=8G --innodb_buffer_pool_instances=16
MySQL的> SELECT @@innodb_buffer_pool_size/1024/1024/1024;
+ ------------------------------------------ +
| @@ innodb_buffer_pool_size / 1024/1024/1024 |
+ ------------------------------------------ +
| 8.000000000000 |
+ ------------------------------------------ +

在这个例子中, innodb_buffer_pool_size设置为9G,并 innodb_buffer_pool_instances设置为16innodb_buffer_pool_chunk_size128M,这是默认值。在这种情况下,9G不是innodb_buffer_pool_instances=16 * 的倍数 innodb_buffer_pool_chunk_size=128M,因此innodb_buffer_pool_size被调整为* 10G这是innodb_buffer_pool_chunk_size* 的下一个倍数 innodb_buffer_pool_instances 不小于指定的缓冲池大小。

外壳> mysqld --innodb_buffer_pool_size=9G --innodb_buffer_pool_instances=16
MySQL的> SELECT @@innodb_buffer_pool_size/1024/1024/1024;
+ ------------------------------------------ +
| @@ innodb_buffer_pool_size / 1024/1024/1024 |
+ ------------------------------------------ +
| 10.000000000000 |
+ ------------------------------------------ +
配置InnoDB缓冲池块大小

innodb_buffer_pool_chunk_size 可以以1MB(1048576字节)为单位增加或减少,但只能在启动时,命令行字符串或MySQL配置文件中修改。

命令行:

外壳> mysqld --innodb_buffer_pool_chunk_size=134217728

配置文件:

的[mysqld]
innodb_buffer_pool_chunk_size = 134217728

更改时适用以下条件 innodb_buffer_pool_chunk_size

  • 如果在 缓冲池初始化时 innodb_buffer_pool_chunk_size值* innodb_buffer_pool_instances大于当前缓冲池大小, innodb_buffer_pool_chunk_size 则会截断为 innodb_buffer_pool_size/ innodb_buffer_pool_instances

    例如,如果缓冲池的初始化大小为2GB(2147483648字节), 4缓冲池实例和块大小1GB(1073741824字节),则块大小会截断为等于innodb_buffer_pool_size/ 的值 innodb_buffer_pool_instances,如下所示:

    外壳> mysqld --innodb_buffer_pool_size=2147483648 --innodb_buffer_pool_instances=4
    --innodb_buffer_pool_chunk_size=1073741824;
    
    MySQL的> SELECT @@innodb_buffer_pool_size;
    + --------------------------- +
    | @@ innodb_buffer_pool_size |
    + --------------------------- +
    | 2147483648 |
    + --------------------------- +
    
    MySQL的> SELECT @@innodb_buffer_pool_instances;
    + -------------------------------- +
    | @@ innodb_buffer_pool_instances |
    + -------------------------------- +
    | 4 |
    + -------------------------------- +
    
    #启动时块大小设置为1GB(1073741824字节),但是
    #截断到innodb_buffer_pool_size / innodb_buffer_pool_instances
    
    MySQL的> SELECT @@innodb_buffer_pool_chunk_size;
    + --------------------------------- +
    | @@ innodb_buffer_pool_chunk_size |
    + --------------------------------- +
    | 536870912 |
    + --------------------------------- +
    
  • 缓冲池大小必须始终等于或innodb_buffer_pool_chunk_size * 的倍数 innodb_buffer_pool_instances如果更改 innodb_buffer_pool_chunk_sizeinnodb_buffer_pool_size 将自动调整为等于或 不小于当前缓冲池大小innodb_buffer_pool_chunk_size * 的倍数 innodb_buffer_pool_instances调整发生在缓冲池初始化时。以下示例演示了此行为:

    #缓冲池的默认大小为128MB(134217728字节)
    
    MySQL的> SELECT @@innodb_buffer_pool_size;
    + --------------------------- +
    | @@ innodb_buffer_pool_size |
    + --------------------------- +
    | 134217728 |
    + --------------------------- +
    
    #块大小也是128MB(134217728字节)
    
    MySQL的> SELECT @@innodb_buffer_pool_chunk_size;
    + --------------------------------- +
    | @@ innodb_buffer_pool_chunk_size |
    + --------------------------------- +
    | 134217728 |
    + --------------------------------- +
    
    #有一个单独的缓冲池实例
    
    MySQL的> SELECT @@innodb_buffer_pool_instances;
    + -------------------------------- +
    | @@ innodb_buffer_pool_instances |
    + -------------------------------- +
    | 1 |
    + -------------------------------- +
    
    #启动时块大小减少1MB(1048576字节)
    #(134217728  -  1048576 = 133169152):
    
    外壳> mysqld --innodb_buffer_pool_chunk_size=133169152
    
    MySQL的> SELECT @@innodb_buffer_pool_chunk_size;
    + --------------------------------- +
    | @@ innodb_buffer_pool_chunk_size |
    + --------------------------------- +
    | 133169152 |
    + --------------------------------- +
    
    #缓冲池大小从134217728增加到266338304
    #缓冲池大小自动调整为等于的值
    #或innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances的倍数
    #不小于当前缓冲池大小
    
    MySQL的> SELECT @@innodb_buffer_pool_size;
    + --------------------------- +
    | @@ innodb_buffer_pool_size |
    + --------------------------- +
    | 266338304 |
    + --------------------------- +

    此示例演示了相同的行为,但具有多个缓冲池实例:

    #缓冲池的默认大小为2GB(2147483648字节)
    
    MySQL的> SELECT @@innodb_buffer_pool_size;
    + --------------------------- +
    | @@ innodb_buffer_pool_size |
    + --------------------------- +
    | 2147483648 |
    + --------------------------- +
    
    #块大小为.5 GB(536870912字节)
    
    MySQL的> SELECT @@innodb_buffer_pool_chunk_size;
    + --------------------------------- +
    | @@ innodb_buffer_pool_chunk_size |
    + --------------------------------- +
    | 536870912 |
    + --------------------------------- +
    
    #有4个缓冲池实例
    
    MySQL的> SELECT @@innodb_buffer_pool_instances;
    + -------------------------------- +
    | @@ innodb_buffer_pool_instances |
    + -------------------------------- +
    | 4 |
    + -------------------------------- +
    
    #启动时块大小减少1MB(1048576字节)
    #(536870912  -  1048576 = 535822336):
    
    外壳> mysqld --innodb_buffer_pool_chunk_size=535822336
    
    MySQL的> SELECT @@innodb_buffer_pool_chunk_size;
    + --------------------------------- +
    | @@ innodb_buffer_pool_chunk_size |
    + --------------------------------- +
    | 535822336 |
    + --------------------------------- +
    
    #缓冲池大小从2147483648增加到4286578688
    #缓冲池大小自动调整为等于的值
    #或innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances的倍数
    #不小于当前缓冲池大小2147483648
    
    MySQL的> SELECT @@innodb_buffer_pool_size;
    + --------------------------- +
    | @@ innodb_buffer_pool_size |
    + --------------------------- +
    | 4286578688 |
    + --------------------------- +
    

    更改时应该小心 innodb_buffer_pool_chunk_size,因为更改此值可以增加缓冲池的大小,如上面的示例所示。在更改之前 innodb_buffer_pool_chunk_size,计算效果 innodb_buffer_pool_size 以确保生成的缓冲池大小可接受。

注意

为避免潜在的性能问题,块(innodb_buffer_pool_size/ innodb_buffer_pool_chunk_size的数量不应超过1000个。

在线配置InnoDB缓冲池大小

innodb_buffer_pool_size 配置选项可以动态使用设置 SET声明,让您调整缓冲池无需重新启动服务器。例如:

MySQL的> SET GLOBAL innodb_buffer_pool_size=402653184;

通过执行活动事务和操作 InnoDB在调整缓冲池的大小之前,应完成API。启动调整大小操作时,直到所有活动事务完成后才会启动操作。一旦调整大小操作正在进行中,需要访问缓冲池的新事务和操作必须等到调整大小操作完成。规则的例外是,当缓冲池被碎片整理时,允许对缓冲池的并发访问,并且当缓冲池大小减小时撤回页面。允许并发访问的一个缺点是它可能导致暂时缺少可用页面而页面正在被撤销。

注意

如果在缓冲池调整大小操作开始后启动,嵌套事务可能会失败。

监控在线缓冲池调整进度

Innodb_buffer_pool_resize_status 报告缓冲池大小调整的进展。例如:

MySQL的> SHOW STATUS WHERE Variable_name='InnoDB_buffer_pool_resize_status';
+ ---------------------------------- + -------------- -------------------- +
| 变量名| 值|
+ ---------------------------------- + -------------- -------------------- +
| Innodb_buffer_pool_resize_status | 还调整其他哈希表的大小。|
+ ---------------------------------- + -------------- -------------------- +

缓冲池调整大小进度也会记录在服务器错误日志中。此示例显示增加缓冲池大小时记录的注释:

[Note] InnoDB:将缓冲池的大小从134217728调整为4294967296.(unit = 134217728)
[注] InnoDB:禁用自适应散列索引。
[注意] InnoDB:缓冲池0:31块(253952块)被添加。
[注意] InnoDB:缓冲池0:哈希表被调整大小。
[注意] InnoDB:在lock_sys,自适应哈希索引,字典中调整大小的哈希表。
[注] InnoDB:完成将缓冲池的大小从134217728调整为4294967296。
[注] InnoDB:重新启用自适应哈希索引。

此示例显示减小缓冲池大小时记录的注释:

[Note] InnoDB:将缓冲池的大小从4294967296调整为134217728.(unit = 134217728)
[注] InnoDB:禁用自适应散列索引。
[注] InnoDB:缓冲池0:开始撤销最后的253952块。
[注意] InnoDB:缓冲池0:从空闲列表中提取了253952个块。试图重新定位0页。
(253952分之253952)
[注意] InnoDB:缓冲池0:撤销目标253952块。
[注意] InnoDB:缓冲池0:31块(253952块)被释放。
[注意] InnoDB:缓冲池0:哈希表被调整大小。
[注意] InnoDB:在lock_sys,自适应哈希索引,字典中调整大小的哈希表。
[注意] InnoDB:完成调整缓冲池从4294967296到134217728。
[注] InnoDB:重新启用自适应哈希索引。
在线缓冲池调整内部组件

调整大小操作由后台线程执行。当增加缓冲池的大小时,调整大小操作:

  • 添加页面chunks(块大小由其定义 innodb_buffer_pool_chunk_size

  • Coverts哈希表,列表和指针在内存中使用新地址

  • 将新页面添加到空闲列表中

当这些操作正在进行时,其他线程将被阻止访问缓冲池。

减小缓冲池的大小时,调整大小操作:

  • 对缓冲池进行碎片整理并撤销(释放)页面

  • 删除页面chunks(块大小由其定义 innodb_buffer_pool_chunk_size

  • 转换哈希表,列表和指针以在内存中使用新地址

在这些操作中,只对缓冲池进行碎片整理和撤销页面,可以让其他线程同时访问缓冲池。

14.6.3.3配置多个缓冲池实例

对于缓冲池在数GB范围内的系统,通过在不同线程读取和写入缓存页面时减少争用,将缓冲池划分为不同的实例可以提高并发性。此功能通常用于缓冲池大小在数GB范围内的系统。使用innodb_buffer_pool_instances 配置选项配置多个缓冲池实例 ,您也可以调整该 innodb_buffer_pool_size值。

InnoDB缓冲池很大时,可以通过从内存中检索来满足许多数据请求。您可能会遇到来自尝试一次访问缓冲池的多个线程的瓶颈。您可以启用多个缓冲池以最大限度地减少此争用。存储在缓冲池中或从中读取的每个页面都使用散列函数随机分配给其中一个缓冲池。每个缓冲池管理自己的空闲列表,刷新列表,LRU以及连接到缓冲池的所有其他数据结构,并受其自己的缓冲池互斥锁保护。

要启用多个缓冲池实例,请将innodb_buffer_pool_instances配置选项设置为 大于1(默认值)最大为64(最大值)的值。此选项只有在您设置innodb_buffer_pool_size为1GB或更大的大小时才会生效 您指定的总大小被分配到所有缓冲池中。为了获得最佳效率,指定的组合 innodb_buffer_pool_instancesinnodb_buffer_pool_size,使得每个缓冲池实例是至少为1GB。

有关修改InnoDB缓冲池大小的信息,请参见第14.6.3.2节“配置InnoDB缓冲池大小”

14.6.3.4使缓冲池抗扫描

与使用严格的LRU 算法不同,InnoDB它使用一种技术来最小化导入缓冲池的数据量, 并且不会再次访问。我们的目标是确保经常访问(热门)的页面保留在缓冲池中,即使预读全表扫描 带入可能或可能未被访问的新块。

新读取的块被插入到LRU列表的中间。所有新读取的页面都插入在默认位置3/8从LRU列表尾部的位置当页面首次在缓冲池中访问时,这些页面将移动到列表的最前面(最近使用的一端)。因此,永远不会被访问的页面永远不会将它放到LRU列表的前面,并且比使用严格的LRU方法更快地老化这种安排将LRU列表分成两段,其中插入点下游的页面被认为是 ”的,并且是LRU驱逐的理想受害者。

有关InnoDB缓冲池内部工作原理 和LRU算法细节的说明,请参见第14.6.3.1节“InnoDB缓冲池”

您可以控制LRU列表中的插入点,并选择是否InnoDB对通过表或索引扫描进入缓冲池的块应用相同的优化。配置参数 innodb_old_blocks_pct控制LRU列表的百分比默认值 innodb_old_blocks_pct37,对应于原始固定比例3/8。值的范围是5(缓冲池中的新页面非常快速地老化)到95 (只有5%的缓冲池是为热页面保留的,使算法接近熟悉的LRU策略)。

保持缓冲池不被预读搅动的优化可以避免由于表或索引扫描造成的类似问题。在这些扫描中,数据页面通常会连续快速访问几次,并且不会再次触摸。配置参数 innodb_old_blocks_time 指定首次访问页面之后的时间窗口(以毫秒为单位),在此期间,可以在不移动到LRU列表的前端(最近使用的末端)的情况下访问它。innodb_old_blocks_timeis 的默认值 1000增加此值会使越来越多的块从缓冲池中快速老化。

这两个innodb_old_blocks_pctinnodb_old_blocks_time是动态的,全球性,可以在MySQL选项文件(指定my.cnfmy.ini)在与运行时或更改SET GLOBAL 命令。更改设置需要 SUPER特权。

为了帮助您评估设置这些参数的效果,该 SHOW ENGINE INNODB STATUS命令会报告缓冲池统计信息。有关详细信息,请参见 第14.6.3.9节“使用InnoDB标准监视器监视缓冲池”

由于这些参数的影响因硬件配置,数据和工作负载的细节而异,因此可以在基准测试中验证效果,然后在任何性能关键或生产环境中更改这些设置。

在混合工作负载中,大多数活动都是OLTP类型,并且定期批量报告查询会导致大扫描,因此在innodb_old_blocks_time批处理运行期间设置值 可以帮助保持缓冲池中正常工作负载的工作集。

扫描不能完全放入缓冲池的大型表时,设置 innodb_old_blocks_pct为较小的值会使只读取一次的数据占用大量缓冲池。例如,设置 innodb_old_blocks_pct=5将这个只读取一次的数据限制到缓冲池的5%。

扫描适合内存的小表时,在缓冲池内移动页面的开销较小,因此您可以将innodb_old_blocks_pct保留 为默认值,甚至更高,例如 innodb_old_blocks_pct=50

innodb_old_blocks_time 参数 的影响 比参数更难预测 innodb_old_blocks_pct ,相对较小,并且随工作量而变化更大。为了达到最佳的价值,如果调整后的性能改善innodb_old_blocks_pct不够充分,可以自行制定基准

14.6.3.5配置InnoDB缓冲池预取(预读)

一个预读请求是I / O请求预取的多个页面 缓冲池 异步,在期待这些页面将很快需要。请求在一个范围内引入所有页面 InnoDB使用两个预读算法来提高I / O性能:

线性预读是一项技术,可根据顺序访问的缓冲池中的页面快速预测可能需要的页面。InnoDB 通过使用配置参数调整触发异步读取请求所需的顺序页面访问次数,您可以控制何时执行预读操作 innodb_read_ahead_threshold在添加此参数之前,InnoDB只会计算在读取当前范围的最后一页时是否对整个下一个范围发出异步预取请求。

配置参数 innodb_read_ahead_threshold 控制InnoDB检测顺序页面访问模式的敏感程度。如果从某个范围顺序读取的页数大于或等于 innodb_read_ahead_threshold,则 InnoDB启动整个后续范围的异步预读操作。 innodb_read_ahead_threshold可以设置为0-64之间的任何值。缺省值是56.值越高,访问模式检查越严格。例如,如果将该值设置为48,则InnoDB 只有在顺序访问当前范围中的48页时才会触发线性预读请求。如果值是8,InnoDB即使按顺序访问范围内的最少8页,也会触发异步预读。您可以在MySQL 配置文件中设置此参数的值,或者使用SET GLOBAL需要SUPER特权命令 动态更改它

随机预读是一种技术,可根据缓冲池中已有的页面快速预测何时需要页面,而不管这些页面的读取顺序如何。如果在缓冲池中找到来自同一范围的连续13个页面,则会 InnoDB异步发出请求以预取该范围的其余页面。要启用此功能,请将配置变量设置 innodb_random_read_aheadON

SHOW ENGINE INNODB STATUS命令显示统计信息以帮助您评估预读算法的有效性。统计数据包括以下全局状态变量的计数器信息:

这些信息在微调innodb_random_read_ahead 设置时非常有用

有关I / O性能的更多信息,请参见 第8.5.8节“优化InnoDB磁盘I / O”第8.12.2节“优化磁盘I / O”

14.6.3.6配置InnoDB缓冲池刷新

InnoDB在后台执行某些任务,包括冲洗脏页从(那些已更改但尚未写入数据库文件页)缓冲池

InnoDB当缓冲池中脏页面的百分比达到由innodb_max_dirty_pages_pct_lwm定义的低水印设置时,开始刷新缓冲池页面 此选项旨在控制缓冲池中脏页的比例,并理想地防止脏页达到的百分比 innodb_max_dirty_pages_pct如果缓冲池中脏页的百分比超过 innodb_max_dirty_pages_pct,则 InnoDB开始积极地刷新缓冲池页面。

InnoDB根据重做日志生成的速度和当前刷新率,使用算法估计所需的刷新率。其目的是通过确保缓冲区刷新活动与保持缓冲池清洁的需要相一致来平滑整体性能 自动调整刷新速率有助于避免吞吐量突然下降,因为过多的缓冲池刷新限制了普通读写活动可用的I / O容量。

InnoDB以循环方式使用其日志文件。在重用日志文件的一部分之前, InnoDB将所有重做条目包含在该日志文件部分中的脏缓冲池页面刷新到磁盘上,这个过程称为 尖锐检查点如果工作负载是写入密集型的,它会生成很多重做信息,全部写入日志文件。如果日志文件中的所有可用空间都用完,则会出现尖锐的检查点,导致吞吐量暂时下降。即使innodb_max_dirty_pages_pct没有达到这种情况也会发生

InnoDB通过测量缓冲池中脏页的数量和生成重做的速率,使用启发式算法来避免这种情况。根据这些数字,InnoDB决定每秒钟从缓冲池刷新多少脏页。这种自适应算法能够处理工作负载的突然变化。

内部基准测试表明,该算法不仅可以保持一段时间的吞吐量,还可以显着提高整体吞吐量。

由于自适应刷新可以显着影响工作负载的I / O模式,因此innodb_adaptive_flushing 可以使用 配置参数关闭此功能。innodb_adaptive_flushingis 的默认值 ON启用自适应刷新算法。您可以在MySQL选项文件(my.cnfmy.ini)中设置此参数的值,或者使用SET GLOBAL 需要SUPER特权命令来动态更改它

有关微调InnoDB 缓冲池刷新行为的信息,请参见第14.6.3.7节“微调InnoDB缓冲池刷新

有关InnoDBI / O性能的更多信息,请参见第8.5.8节“优化InnoDB磁盘I / O”

14.6.3.7微调InnoDB缓冲池刷新

配置选项 innodb_flush_neighborsinnodb_lru_scan_depth让你微调方面 冲洗的过程中 InnoDB 缓冲池

  • innodb_flush_neighbors

    指定是否从缓冲池中清除页面也会在相同范围内刷新其他脏页面。当表格数据存储在传统的 HDD存储设备上时,与在不同时间冲刷单独页面相比,在一个操作中冲刷相邻页面减少了I / O开销(主要用于磁盘搜索操作)。对于存储在SSD上的表格数据,查找时间不是一个重要因素,您可以禁用此设置以分散写入操作。

  • innodb_lru_scan_depth

    为每个缓冲池实例指定缓冲池LRU下多远,页面清理器线程扫描寻找要刷新的脏页面。这是每秒执行一次的后台操作。

这些选项主要有助于编写密集型 工作负载如果DML活动很繁重 ,如果不够积极,刷新可能会落后,导致缓冲池中内存使用过多; 或者,由于刷新导致的磁盘写入可能会使您的I / O容量饱和,如果这种机制过于激进的话。理想的设置取决于您的工作负载,数据访问模式和存储配置(例如,数据是存储在HDD还是SSD设备上)。

对于工作负载较重的系统 或工作负载波动较大的系统,可以使用多个配置选项来微调刷新 行为InnoDB

这些选项会导入选项使用的公式 innodb_adaptive_flushing

innodb_adaptive_flushinginnodb_io_capacityinnodb_max_dirty_pages_pct 选项由以下选项限制或扩展:

InnoDB 自适应冲洗 机制并不适合所有的情况。重做日志 存在填满危险时,它提供了最大的好处innodb_adaptive_flushing_lwm 选项指定重做日志容量低水位百分比; 当超过该阈值时, InnoDB即使未由innodb_adaptive_flushing 选项指定,也会启用自适应刷新

如果冲洗活动远远落后,InnoDB 可以冲洗比规定更积极 innodb_io_capacityinnodb_io_capacity_max 表示在这种紧急情况下使用的I / O容量的上限,以便I / O中的峰值不会消耗服务器的所有容量。

InnoDB尝试从缓冲池中刷新数据,以便脏页面的百分比不超过值 innodb_max_dirty_pages_pct默认值 innodb_max_dirty_pages_pct是75。

注意

innodb_max_dirty_pages_pct 设置确定了冲洗活动的目标。它不会影响冲洗的速度。有关管理刷新速率的信息,请参见第14.6.3.6节“配置InnoDB缓冲池刷新

innodb_max_dirty_pages_pct_lwm 选项指定一个低水位值,该值表示启用预先刷新以控制脏页比率并理想地防止脏页达到百分比的脏页的百分比 innodb_max_dirty_pages_pct的值 innodb_max_dirty_pages_pct_lwm=0 禁用冲洗前行为。

上面提到的大多数选项最适用于长时间运行写入繁重工作负载的服务器,并且几乎没有减少加载时间以赶上等待写入磁盘的更改。

innodb_flushing_avg_loops 定义了InnoDB保持先前计算的刷新状态快照的迭代次数 ,其控制自适应刷新响应前景负载变化的速度。设置较高的值 innodb_flushing_avg_loops意味着InnoDB保持之前计算的快照时间更长,所以自适应刷新响应速度更慢。较高的值也会减少前景和后台工作之间的正反馈,但设置较高值时,重要的是确保InnoDB重做日志利用率不会达到75%(异步刷新开始的硬编码限制),并且 innodb_max_dirty_pages_pct 设置可将脏页数保持在适合工作负载的级别。

具有一致工作负载的系统 innodb_log_file_size,大小不高的重做日志空间利用率达到75%的尖峰应使用较高的 innodb_flushing_avg_loops值,以尽可能保持平滑。对于极端负载峰值或日志文件不提供大量空间的系统,请考虑较小的 innodb_flushing_avg_loops 值。较小的值允许冲洗以紧密跟踪负载,并有助于避免达到75%的重做日志空间利用率。

14.6.3.8保存和恢复缓冲池状态

为了减少重新启动服务器后预热时间,请InnoDB在服务器关闭时为每个缓冲池保存最近使用的页面的百分比,并在服务器启动时恢复这些页面。存储的最近使用的页面的百分比由innodb_buffer_pool_dump_pct 配置选项定义

在重新启动繁忙的服务器后,通常会有一个预热期,吞吐量稳步增加,因为缓冲池中的磁盘页被带回到内存中(因为查询,更新了相同的数据)。在启动时恢复缓冲池的功能通过在重新启动之前重新加载缓冲池中的磁盘页而缩短了预热期,而不是等待DML操作访问相应的行。此外,I / O请求可以大批量执行,从而使整体I / O更快。页面加载发生在后台,并且不会延迟数据库启动。

除了在关闭时保存缓冲池状态并在启动时恢复缓冲池状态外,您还可以在服务器运行时随时保存和恢复缓冲池状态。例如,您可以在稳定的工作负载下达到稳定的吞吐量后保存缓冲池的状态。运行将数据页面带入缓冲池的报表或维护作业(仅针对这些操作请求)或运行其他非典型工作负载后,还可以恢复以前的缓冲池状态。

尽管一个缓冲池的大小可能是几千兆字节,但InnoDB通过比较保存到磁盘的缓冲池数据很小。只有定位适当页面所需的表空间ID和页面ID才会保存到磁盘。该信息来自 表格。默认情况下,表空间ID和页面ID数据保存在名为的文件中,该文件 保存在 数据目录中。文件名和位置可以使用 配置参数进行修改 INNODB_BUFFER_PAGE_LRU INFORMATION_SCHEMAib_buffer_poolInnoDBinnodb_buffer_pool_filename

由于数据与常规数据库操作一样,缓存在缓冲池中并且超出缓冲池,因此,如果最近更新了磁盘页面,或者如果DML操作涉及尚未加载的数据,则没有问题。加载机制跳过不存在的请求页面。

底层机制涉及调度执行转储和加载操作的后台线程。

压缩表中的磁盘页面以压缩格式加载到缓冲池中。在DML操作期间访问页面内容时,页面像往常一样解压缩。由于解压缩页面是CPU密集型进程,因此在连接线程中执行操作而不是执行缓冲池恢复操作的单个线程的并发性效率更高。

以下主题描述了与保存和恢复缓冲池状态相关的操作:

配置缓冲池页面的转储百分比

在从缓冲池中转储页面之前,可以通过设置innodb_buffer_pool_dump_pct 选项来配置要转储的最近使用的缓冲池页面的百分比 如果您计划在服务器运行时转储缓冲池页面,则可以动态配置该选项:

SET GLOBAL innodb_buffer_pool_dump_pct = 40;

如果您计划在服务器关闭时转储缓冲池页面,请innodb_buffer_pool_dump_pct 在您的配置文件中进行设置

的[mysqld]
innodb_buffer_pool_dump_pct = 40

innodb_buffer_pool_dump_pct 缺省值从100改为(转储所有页面)至25(转储最近最常使用的页面的25%)在MySQL 5.7的时候 innodb_buffer_pool_dump_at_shutdowninnodb_buffer_pool_load_at_startup 被默认启用。

在关机时保存缓冲池状态并在启动时恢复

要在关闭服务器时保存缓冲池的状态,请在关闭服务器之前发出以下语句:

SET GLOBAL innodb_buffer_pool_dump_at_shutdown = ON;

innodb_buffer_pool_dump_at_shutdown 是默认启用的。

要在服务器启动时恢复缓冲池状态,请在启动服务器时指定--innodb_buffer_pool_load_at_startup 选项:

mysqld --innodb_buffer_pool_load_at_startup = ON;

innodb_buffer_pool_load_at_startup 是默认启用的。

在线保存和恢复缓冲池状态

要在MySQL服务器运行时保存缓冲池的状态,请发出以下语句:

SET GLOBAL innodb_buffer_pool_dump_now = ON;

要在MySQL运行时恢复缓冲池状态,请发出以下语句:

SET GLOBAL innodb_buffer_pool_load_now = ON;
显示缓冲池转储进度

要将缓冲池状态保存到磁盘时显示进度,请发出以下语句:

SHOW STATUS LIKE'Innodb_buffer_pool_dump_status';

如果操作尚未开始,则返回未开始如果操作完成,则打印完成时间(例如,完成时间为110505 12:18:02)。如果操作正在进行中,则提供状态信息(例如,转储缓冲池5/7,页面237/2873)。

显示缓冲池负载进度

要在加载缓冲池时显示进度,请发出以下语句:

SHOW STATUS LIKE'Innodb_buffer_pool_load_status';

如果操作尚未开始,则返回未开始如果操作完成,则打印完成时间(例如,在110505 12:23:24完成)。如果操作正在进行中,则提供状态信息(例如,加载的123/22301页)。

中止缓冲池加载操作

要中止缓冲池加载操作,请发出以下语句:

SET GLOBAL innodb_buffer_pool_load_abort = ON;
使用性能模式监视缓冲池负载进度

您可以使用性能架构监视缓冲池负载进度

以下示例演示如何启用 stage/innodb/buffer pool loadstage事件工具和相关的使用者表以监视缓冲池加载进度。

有关此示例中使用的缓冲池转储和加载过程的信息,请参见 第14.6.3.8节“保存和恢复缓冲池状态”有关Performance Schema阶段事件工具和相关使用者的信息,请参见 第25.11.5节“性能模式阶段事件表”

  1. 启用stage/innodb/buffer pool load仪器:

    MySQL的> UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' 
           WHERE NAME LIKE 'stage/innodb/buffer%';
    
  2. 启用舞台活动消费表,其中包括 events_stages_currentevents_stages_history,和 events_stages_history_long

    MySQL的> UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' 
           WHERE NAME LIKE '%stages%';
    
  3. 通过启用转储当前缓冲池状态 innodb_buffer_pool_dump_now

    MySQL的> SET GLOBAL innodb_buffer_pool_dump_now=ON;
    
  4. 检查缓冲池转储状态以确保操作已完成。

    MySQL的> SHOW STATUS LIKE 'Innodb_buffer_pool_dump_status'\G
    *************************** 1. row ******************** *******
    变量名称:Innodb_buffer_pool_dump_status
            价值:缓冲池(s)转储完成在150202 16:38:58
    
  5. 通过启用加载缓冲池 innodb_buffer_pool_load_now

    MySQL的> SET GLOBAL innodb_buffer_pool_load_now=ON;
    
  6. 通过查询性能模式events_stages_current来检查缓冲池加载操作的当前状态 WORK_COMPLETED列显示加载的缓冲池页面的数量。WORK_ESTIMATED列以页面形式提供了剩余工作的估计值。

    MySQL的> SELECT EVENT_NAME, WORK_COMPLETED, WORK_ESTIMATED
           FROM performance_schema.events_stages_current;
    + ------------------------------- + ---------------- + ---------------- +
    | EVENT_NAME | WORK_COMPLETED | WORK_ESTIMATED |
    + ------------------------------- + ---------------- + ---------------- +
    | stage / innodb /缓冲池加载| 5353 | 7167 |
    + ------------------------------- + ---------------- + ---------------- +
    

    events_stages_current 如果缓冲池加载操作完成,表将返回一个空集。在这种情况下,您可以检查 events_stages_history表格以查看已完成事件的数据。例如:

    MySQL的> SELECT EVENT_NAME, WORK_COMPLETED, WORK_ESTIMATED 
           FROM performance_schema.events_stages_history;
    + ------------------------------- + ---------------- + ---------------- +
    | EVENT_NAME | WORK_COMPLETED | WORK_ESTIMATED |
    + ------------------------------- + ---------------- + ---------------- +
    | stage / innodb /缓冲池加载| 7167 | 7167 |
    + ------------------------------- + ---------------- + ---------------- +
    
注意

您也可以在启动时使用性能架构加载缓冲池时监控缓冲池负载进度 innodb_buffer_pool_load_at_startup在这种情况下,stage/innodb/buffer pool load必须在启动时启用仪器和相关使用者。有关更多信息,请参见 第25.3节“性能架构启动配置”

14.6.3.9使用InnoDB标准监视器监视缓冲池

InnoDB标准监视器输出可以使用 SHOW ENGINE INNODB STATUS,提供与InnoDB缓冲池操作有关的度量缓冲池度量标准位于标准监视器输出BUFFER POOL AND MEMORY部分,InnoDB并且类似于以下内容:

----------------------
缓冲池和内存
----------------------
总大内存分配2198863872
分配了字典内存776332
缓冲池大小131072
空闲缓冲区124908
数据库页面5720
旧数据库页面2071
修改的数据页面910
等待读取0
等待写入:LRU 0,刷新列表0,单个页面0
年轻的4页,而不是年轻的0
0.10个年轻人/ s,0.00个非年轻人/ s
页面读取197,创建5523,写入5060
0.00读/秒,190.89创/秒,244.94写/秒
缓冲池命中率为1000/1000,年轻化率为0/1000
0/1000
提前读取的页数为0.00 / s,无需访问驱逐0.00 /秒,随机读取
前进0.00 /秒
LRU len:5720,unzip_LRU len:0
I / O sum [0]:cur [0],unzip sum [0]:cur [0]

下表介绍了InnoDBInnoDB标准监视器报告的缓冲池度量标准。

注意

InnoDB 标准监视器输出中 提供的每秒平均值基于自InnoDB上次打印标准监视器输出以来所用的时间

表14.2 InnoDB缓冲池度量标准

名称 描述
分配的内存总量 为缓冲池分配的总内存(以字节为单位)。
分配字典内存 InnoDB数据字典分配的总内存(以字节为单位)。
缓冲池大小 分配给缓冲池的页面总大小。
免费缓冲区 缓冲池空闲列表的页面总大小。
数据库页面 缓冲池LRU列表的页面总大小。
旧的数据库页面 缓冲池旧LRU子列表的页面总大小。
修改数据库页面 当前在缓冲池中修改的页数。
等待读取 等待读入缓冲池的缓冲池页数。
等待写入LRU 要从LRU列表底部写入的缓冲池中旧脏页的数量。
等待写入清单 在检查点中要刷新的缓冲池页面的数量。
等待写入单个页面 缓冲池中挂起的独立页面写入次数。
页面变得年轻 缓冲池LRU列表中的年轻页面总数(移至页面的子列表头部)。
页面不是年轻的 在缓冲池LRU列表中没有变得年轻的页面总数(保留在 子列表中而没有变得年轻的页面)。
扬斯/秒 在缓冲池LRU列表中访问旧页面的平均每秒导致页面变得年轻。请参阅本表后面的注释以获取更多信息。
非杨氏/ s的 缓冲池LRU列表中旧页面的每秒平均访问量导致页面不够年轻。请参阅本表后面的注释以获取更多信息。
读取页面 从缓冲池中读取的总页数。
已创建页面 在缓冲池内创建的页面总数。
撰写的页面 从缓冲池写入的总页数。
读取/秒 每秒缓冲池页面读取的平均每秒数。
创建/秒 每秒创建的缓冲池页面的每秒平均数量。
写入/秒 每秒平均缓冲池页面写入次数。
缓冲池命中率 从缓冲池内存读取的页面的缓冲池页面命中率与磁盘存储的页面命中率。
年轻化率 页面访问的平均命中率导致页面变得年轻。请参阅本表后面的注释以获取更多信息。
不(年轻率) 页面访问的平均点击率并未导致页面年轻化。请参阅本表后面的注释以获取更多信息。
预读页面 预读操作的每秒平均值。
被驱逐但无法访问的页面 被逐出的页面的平均每秒不从缓冲池访问。
随机预读 随机预读操作的每秒平均值。
LRU len 缓冲池LRU列表的页面总大小。
unzip_LRU len 缓冲池unzip_LRU列表的总页面大小。
I / O总和 最近50秒访问的缓冲池LRU列表页面的总数。
I / O当前 访问的缓冲池LRU列表页面的总数。
I / O解压缩和 访问的缓冲池unzip_LRU列表页面的总数。
I / O解压缩 访问的缓冲池unzip_LRU列表页面的总数。

备注

  • youngs/s指标只涉及旧页面。它基于对页面的访问次数而不是页数。可以对给定页面进行多次访问,所有这些都被计算在内。如果youngs/s在没有发生大扫描时看到非常低的 值,则可能需要缩短延迟时间或增加用于旧子列表的缓冲池的百分比。增加百分比会使旧的子列表变大,因此该子列表中的页面需要更长时间才能移动到尾部并被驱逐。这增加了页面被再次访问并变得年轻的可能性。

  • non-youngs/s指标只涉及旧页面。它基于对页面的访问次数而不是页数。可以对给定页面进行多次访问,所有这些都被计算在内。如果non-youngs/s在进行大型表扫描(以及大量扫描youngs/s看不到很多,请增加延迟值。

  • young-making率占访问到所有缓冲池页面,不只是访问旧子列表页面。young-making速度和 not速率通常不加起来的整体缓冲池命中率。页面在旧子列表中的命中会导致页面移动到新的子列表,但页面在新子列表中的命中会导致页面仅在与头部有一定距离时才移动到列表的头部。

  • not (young-making rate)是页面访问的平均命中率,由于innodb_old_blocks_time未达到定义的延迟,或者由于新子列表中的页面点击未导致页面移动到头部,所以页面访问的平均命中率未导致页面变得年轻 此速率用于访问所有缓冲池页面,而不仅仅访问旧子列表中的页面。

InnoDB缓冲池 服务器状态变量,该 INNODB_BUFFER_POOL_STATS表提供了许多InnoDB标准监视器输出中找到的相同缓冲池指标 有关该INNODB_BUFFER_POOL_STATS表的更多信息 ,请参见 示例14.10,“查询INNODB_BUFFER_POOL_STATS表”

14.6.4配置InnoDB的内存分配器

InnoDB开发时,随操作系统和运行时库提供的内存分配器往往缺乏性能和可扩展性。那时,没有为多核CPU调优的内存分配器库。因此,InnoDBmem子系统中实现了自己的内存分配器这个分配器由一个互斥体保护,这可能会成为一个 瓶颈InnoDB还在系统分配器(mallocfree周围实现了一个包装接口,同样由单个互斥体保护。

今天,随着多核系统变得越来越广泛,随着操作系统的成熟,在配备操作系统的内存分配器方面已经取得了重大进展。这些新的内存分配器执行得更好,比以往更具可扩展性。大多数工作负载,尤其是那些内存经常分配和释放的工作负载(如多表连接)可以使用高度调优的内存分配器而不是内部的 InnoDB特定内存分配器。

InnoDB通过innodb_use_sys_malloc在MySQL选项文件(my.cnfmy.ini)中设置系统配置参数的值, 可以控制是使用其自己的内存分配器还是操作系统的分配器 如果设置为ON1(默认),InnoDB使用mallocfree ,而不是底层系统的功能管理存储池本身。该参数不是动态的,只有在系统启动时才生效。要继续使用 InnoDB内存分配器,请设置 innodb_use_sys_malloc0

InnoDB内存分配器被禁用时, InnoDB忽略参数的值 innodb_additional_mem_pool_sizeInnoDB内存分配器用来满足分配请求额外的内存池,而无需退回到系统内存分配器。InnoDB内存分配器被禁用时,所有这些分配请求都由系统内存分配器完成。

在使用动态链接的类Unix系统上,替换内存分配器可能与创建环境变量LD_PRELOADLD_LIBRARY_PATH指向实现分配器的动态库一样简单 在其他系统上,可能需要重新链接。请参阅您选择的内存分配程序库的文档。

由于InnoDB在使用系统内存分配程序(innodb_use_sys_mallocis ON时无法跟踪所有内存使用情况,因此命令输出中的BUFFER POOL AND MEMORY部分SHOW ENGINE INNODB STATUS仅包含“已分配总内存 ”中的缓冲池统计信息任何使用mem子系统或使用 分配的内存都将ut_malloc被排除。

注意

innodb_use_sys_mallocinnodb_additional_mem_pool_size 在MySQL 5.6中被弃用,并在MySQL 5.7中被删除。

有关InnoDB内存使用情况对性能影响的更多信息 ,请参见 第8.10节“缓冲和高速缓存”

14.6.5配置InnoDB变更缓存

INSERTUPDATEDELETE操作是在一个表来执行,索引列的值(辅助键的特别的值)在未排序的顺序常常是,需要大量的I / O以使辅助索引是最新的。 InnoDB有一个 更改缓冲区,用于在相关页面不在 缓冲池中时将更改缓存到辅助索引条目 ,从而避免通过从磁盘立即读取页面而导致的昂贵的I / O操作。缓存的更改在页面加载到缓冲池时合并,并且更新的页面稍后刷新到磁盘。InnoDB主线程在服务器几乎空闲时以及缓慢关闭期间合并缓存的更改

因为它可能导致更少的磁盘读取和写入操作,所以对于I / O绑定的工作负载,更改缓冲区功能是最有价值的,例如具有大量DML操作(如批量插入)的应用程序。

但是,更改缓冲区占用了缓冲池的一部分,减少了可用于缓存数据页的内存。如果工作集几乎适合缓冲池,或者如果您的表具有相对较少的二级索引,则禁用更改缓冲可能会很有用。如果工作集完全适合缓冲区,更改缓冲不会带来额外的开销,因为它仅适用于不在缓冲池中的页。

您可以InnoDB 使用innodb_change_buffering 配置参数控制执行更改缓冲 的范围您可以启用或禁用缓冲插入,删除操作(索引记录最初标记为删除时)和清除操作(索引记录物理删除时)。更新操作是插入和删除的组合。默认 innodb_change_buffering值是 all

允许的innodb_change_buffering 值包括:

  • all

    默认值:缓冲区插入,删除标记操作和清除。

  • none

    不要缓冲任何操作。

  • inserts

    缓冲区插入操作。

  • deletes

    缓冲区删除标记操作。

  • changes

    缓冲插入和删除标记操作。

  • purges

    缓冲在后台发生的物理删除操作。

您可以innodb_change_buffering在MySQL选项文件(my.cnfmy.ini)中设置 参数,或者使用SET GLOBAL 需要SUPER特权命令动态更改它 更改设置会影响新操作的缓冲; 现有缓冲条目的合并不受影响。

有关相关信息,请参见 第14.4.2节“更改缓冲区”有关配置更改缓冲区大小的信息,请参见 第14.6.5.1节“配置更改缓冲区的最大大小”

14.6.5.1配置更改缓冲区的最大大小

从MySQL 5.6.2开始,使用 innodb_change_buffer_max_size 配置选项可以将更改缓冲区的最大大小配置为缓冲池总大小的百分比。默认情况下, innodb_change_buffer_max_size 设置为25.最大设置为50。

您可能会考虑innodb_change_buffer_max_size 在MySQL服务器上增加 大量插入,更新和删除活动,其中更改缓冲区合并跟不上新的更改缓冲区条目,导致更改缓冲区达到其最大大小限制。

您可能会考虑innodb_change_buffer_max_size 使用用于报告的静态数据在MySQL服务器上减少 数据量,或者如果更改缓冲区消耗的内存空间与缓冲池共享的空间过多,则会导致页面比期望的更早退出缓冲池。

使用代表性工作负载测试不同的设置以确定最佳配置。innodb_change_buffer_max_size 设置是动态的,可以在不重新启动服务器的情况下修改设置。

14.6.6配置InnoDB的线程并发

InnoDB使用操作系统 线程处理来自用户事务的请求。(事务InnoDB在提交或回滚之前可能会发出很多请求 。)在具有多核处理器的现代操作系统和服务器上,在上下文切换有效的情况下,大多数工作负载运行良好,对并发线程数没有任何限制。MySQL 5.5及以上版本的可伸缩性改进降低了对内部并发执行线程数量的限制 InnoDB

在线程之间的上下文切换最小化的情况下,InnoDB可以使用许多技术来限制并发执行的操作系统线程的数量(并且因此限制任何时候处理的请求的数量)。InnoDB从用户会话接收到新请求时,如果并发执行的线程数量处于预定义的限制,则新请求会在短时间内休眠,然后再次尝试。睡眠之后无法重新安排的请求被放入先入先出队列中并最终被处理。等待锁的线程不计入并发执行线程的数量。

您可以通过设置配置参数来限制并发线程的数量 innodb_thread_concurrency一旦执行线程的数量达到此限制,其他线程innodb_thread_sleep_delay在被放入队列之前会睡眠数微秒(由配置参数 设置)。

以前,它需要进行实验才能找到最佳值innodb_thread_sleep_delay,并且最佳值可能会根据工作负载而改变。在MySQL 5.6.3及更高版本中,可以将配置选项设置为 innodb_adaptive_max_sleep_delay 允许的最高值 innodb_thread_sleep_delay,并 根据当前的线程调度活动InnoDB自动调整 innodb_thread_sleep_delay向上或向下。这种动态调整有助于线程调度机制在系统轻载时以及接近满负载运行时顺利运行。

innodb_thread_concurrency并发线程数 的默认值 和默认的并发线程数默认限制在各种版本的MySQL和 InnoDBinnodb_thread_concurrencyis 的默认值 0,所以默认情况下并发执行线程的数量没有限制。

InnoDB只有当并发线程数量有限时,才会使线程进入睡眠状态。在线程数没有限制的情况下,所有的竞争都是预定的。也就是说,如果innodb_thread_concurrency0,那么值 innodb_thread_sleep_delay被忽略。

当线程数有限制时(当 innodb_thread_concurrency> 0时),InnoDB通过允许在执行单个SQL语句期间进行的多个请求进入InnoDB而不遵守设置的限制 减少上下文切换开销 innodb_thread_concurrency由于SQL语句(如连接)可能包含多个行操作InnoDB,因此 InnoDB会分配指定数量的 票据,以便以最小的开销重复调度线程。

当一个新的SQL语句启动时,一个线程没有票据,并且必须遵守 innodb_thread_concurrency一旦线程有权输入InnoDB,它将被分配一些门票,它可以用于随后进入InnoDB执行行操作。如果票据用完,线程被驱逐,并且 innodb_thread_concurrency再次被观察到,这可能使线程回到等待线程的先进/先出队列中。当线程再次有资格输入时InnoDB,门票再次分配。分配的票数由全局选项指定 innodb_concurrency_tickets,默认为5000。一旦锁定可用,正在等待锁定的线程将被授予一张票。

这些变量的正确值取决于您的环境和工作负载。尝试一系列不同的值来确定适用于您的应用程序的值。在限制并发执行线程的数量之前,请查看可以提高InnoDB多核和多处理器计算机性能的配置选项,例如 innodb_adaptive_hash_index

有关MySQL线程处理的一般性能信息,请参见第8.12.5.1节“MySQL如何使用线程进行客户端连接”

14.6.7配置背景InnoDB I / O线程数量

InnoDB使用后台 线程来处理各种类型的I / O请求。您可以使用innodb_read_io_threadsinnodb_write_io_threads 配置参数配置服务在数据页上读写I / O的后台线程 数。这些参数分别表示用于读取和写入请求的后台线程的数量。它们在所有支持的平台上都很有效。您可以在MySQL选项文件(my.cnfmy.ini)中为这些参数设置值; 你不能动态改变数值。这些参数的默认值是4和允许值范围从1-64

这些配置选项的目的是为了InnoDB在高端系统上实现 更高的可扩展性。每个后台线程最多可处理256个待处理的I / O请求。后台I / O的主要来源是 预读请求。 InnoDB试图以大多数后台线程平等共享工作的方式平衡传入请求的负载。InnoDB还会尝试将同一范围内的读取请求分配给相同的线程,以增加合并请求的机会。如果您有高端I / O子系统,并且innodb_read_io_threadsSHOW ENGINE INNODB STATUS 输出中看到超过64个 未决读取请求,则可以通过增加值来提高性能 innodb_read_io_threads

在Linux系统上,InnoDB默认情况下使用异步I / O子系统来执行数据文件页面的预读和写请求,这会改变 InnoDB后台线程处理这些类型的I / O请求的方式。有关更多信息,请参见 第14.6.8节“在Linux上使用异步I / O”

有关InnoDBI / O性能的更多信息,请参见第8.5.8节“优化InnoDB磁盘I / O”

14.6.8在Linux上使用异步I / O

InnoDB在Linux上使用异步I / O子系统(本机AIO)来执行数据文件页的预读和写请求。此行为由innodb_use_native_aio 配置选项控制,该选项仅适用于Linux系统,默认情况下处于 启用状态。在其他类Unix系统上,只 InnoDB使用同步I / O。历史上, InnoDB只在Windows系统上使用异步I / O。在Linux上使用异步I / O子系统需要该libaio库。

通过同步I / O,查询线程对I / O请求InnoDB进行排队后台线程一次检索一个排队请求,为每个请求发出一个同步I / O调用。当I / O请求完成且I / O调用返回时,InnoDB处理请求后台线程调用I / O完成例程并返回以处理下一个请求。可以并行处理的请求数是n后台线程n的数量 在哪里 InnoDBInnoDB后台线程的数量 innodb_read_io_threads控制 innodb_write_io_threads请参见 第14.6.7节“配置背景InnoDB I / O线程数”

使用本机AIO,查询线程直接向操作系统发送I / O请求,从而消除后台线程数量所带来的限制。InnoDB后台线程等待I / O事件来表示已完成的请求。当请求完成时,后台线程调用I / O完成例程并继续等待I / O事件。

本机AIO的优势在于,对于I / O受限的系统来说,可扩展性通常会在SHOW ENGINE INNODB STATUS\G输出中显示许多未决的读取/写入操作 使用本机AIO时并行处理的增加意味着I / O调度程序的类型或磁盘阵列控制器的属性对I / O性能有更大的影响。

本机AIO对于I / O密集型系统的潜在缺点是缺乏对同时分派给操作系统的I / O写入请求数量的控制。根据I / O活动的数量和系统功能的不同,调度到操作系统进行并行处理的太多I / O写请求可能会导致I / O读取不足。

如果操作系统中的异步I / O子系统的问题阻止InnoDB启动,则可以使用启动服务器 innodb_use_native_aio=0如果InnoDB检测到潜在问题(例如tmpdir位置, tmpfs文件系统和不支持异步I / O的Linux内核组合),则也可能在启动过程中自动禁用此选项 tmpfs

14.6.9配置InnoDB主线程I / O速率

InnoDB中主线程是一个在后台执行各种任务的线程。这些任务中的大多数都与I / O相关,例如从缓冲池中清除脏页或将插入缓冲区中的更改写入适当的二级索引。主线程尝试以不会对服务器的正常工作产生不利影响的方式执行这些任务。它试图估计可用的空闲I / O带宽,并调整其活动以利用此免费容量。历史上,InnoDB使用了100 IOP(每秒输入/输出操作)的硬编码值作为服务器的总I / O容量。

该参数innodb_io_capacity 表示InnoDB可用的整体I / O容量。此参数应设置为大约系统每秒可执行的I / O操作的数量。该值取决于您的系统配置。何时 innodb_io_capacity设置,主线程根据设置值估计可用于后台任务的I / O带宽。设置该值以 100恢复到旧的行为。

您可以将值设置 innodb_io_capacity为任何数字100或更大。默认值是200,反映了典型的现代I / O设备的性能比MySQL早期的性能更高。通常,以前的默认值100左右的值适用于消费级存储设备,例如高达7200 RPM的硬盘驱动器。更快的硬盘驱动器,RAID配置和固态硬盘从更高的价值中受益。

innodb_io_capacity设置是所有缓冲池实例的总限制。当刷新脏页时,innodb_io_capacity 限制在缓冲池实例中平均分配。有关更多信息,请参阅 innodb_io_capacity系统变量说明。

您可以在MySQL选项文件(my.cnfmy.ini)中设置此参数的值,或者使用SET GLOBAL需要SUPER特权命令来动态更改它

innodb_flush_sync 配置选项使 innodb_io_capacity发生在检查点I / O活动的脉冲串期间被忽略设置。 innodb_flush_sync是默认启用的。

以前,InnoDB主线程还执行任何所需的清除 操作。在MySQL 5.6.5及更高版本中,这些I / O操作将移动到其他后台线程,后台线程的编号由innodb_purge_threads 配置选项控制

有关InnoDB I / O性能的更多信息,请参见 第8.5.8节“优化InnoDB磁盘I / O”

14.6.10配置自旋锁定轮询

很多InnoDB 互斥锁rw锁都保留了很短时间。在多核系统上,线程可以更有效地检查睡眠前是否可以获取互斥锁或rw锁。如果在此轮询期间互斥锁或rw锁可用,则线程可以在同一时间片内立即继续。然而,由多个共享对象线程轮询太频繁会导致缓存乒乓,不同的处理器会使每个其他缓存的部分无效。InnoDB通过在随后的轮询之间等待随机时间来最小化这个问题。延迟被实现为繁忙循环。

您可以使用参数控制测试互斥锁或rw锁之间的最大延迟时间 innodb_spin_wait_delay延迟循环的持续时间取决于C编译器和目标处理器。(在100MHz奔腾时代,延迟单位是1微秒)。在所有处理器内核共享快速高速缓存的系统上,您可以通过设置来减少最大延迟或完全禁用忙碌循环 innodb_spin_wait_delay=0在具有多个处理器芯片的系统上,高速缓存失效的影响可能更为显着,您可能会增加最大延迟。

innodb_spin_wait_delayis 的默认值 6旋转等待延迟是一个动态的全局参数,您可以在MySQL选项文件(my.cnfmy.ini)中指定,或者在运行时使用该命令进行更改,其中是所需的最大延迟。更改设置需要 特权。 SET GLOBAL innodb_spin_wait_delay=delaydelaySUPER

有关InnoDB锁定操作的性能注意事项,请参见 第8.11节“优化锁定操作”

14.6.11配置InnoDB清除调度

InnoDB自动执行清除操作(一种垃圾收集)可以由一个或多个单独的线程执行,而不是作为主线程的一部分通过允许主数据库操作独立于后台发生的维护工作,独立线程的使用提高了可伸缩性。

要控制此功能,请增加配置选项的值innodb_purge_threads如果DML操作集中在单个表或几个表上,请将设置保持为低,以便线程不会彼此竞争访问繁忙表。如果DML操作分散在多个表中,请增加设置。它的最大值是32. innodb_purge_threads是一个非动态配置选项,这意味着它不能在运行时配置。

还有另一个相关配置选项, innodb_purge_batch_size默认值为300,最大值为5000.此选项主要用于试验和调整清除操作,对典型用户应该不感兴趣。

有关InnoDB I / O性能的更多信息,请参见 第8.5.8节“优化InnoDB磁盘I / O”

14.6.12为InnoDB配置优化器统计信息

本节介绍如何为表配置持久性和非持久性优化器统计信息InnoDB

持久性优化器统计信息在服务器重新启动时保持不变,从而实现更高的 计划稳定性和更一致的查询性能。持久优化器统计数据还提供了控制和灵活性以及这些额外的好处:

  • 您可以使用 innodb_stats_auto_recalc 配置选项来控制是否在对表格进行实质性更改后自动更新统计信息。

  • 您可以使用STATS_PERSISTENTSTATS_AUTO_RECALC以及 STATS_SAMPLE_PAGES与条款 CREATE TABLEALTER TABLE声明配置个别表优化统计。

  • 您可以查询mysql.innodb_table_statsmysql.innodb_index_stats中的优化器统计数据

  • 您可以查看表格last_update以查看统计信息上次更新的时间。 mysql.innodb_table_statsmysql.innodb_index_stats

  • 您可以手动修改 mysql.innodb_table_statsmysql.innodb_index_stats表来强制执行特定的查询优化计划,或者在不修改数据库的情况下测试替代计划。

持久优化器统计信息功能默认为启用(innodb_stats_persistent=ON)。

在每次服务器重启时以及在其他操作之后清除非永久性优化器统计信息,并在下一次表访问时重新计算。因此,重新计算统计信息时可能会产生不同的估计值,从而导致执行计划的不同选择和查询性能的变化。

本节还提供了有关估计ANALYZE TABLE复杂性的信息 ,这在尝试实现精确统计和ANALYZE TABLE 执行时间之间的平衡时可能会有用

14.6.12.1配置持久优化器统计参数

持久化优化器统计功能通过将统计数据存储到磁盘并使其在服务器重新启动时保持不变从而提高 计划稳定性,从而 优化器每次对给定查询更可能做出一致的选择。

innodb_stats_persistent=ON当创建或更改单个表 时,优化程序统计信息会保存到磁盘 STATS_PERSISTENT=1innodb_stats_persistent是默认启用的。

以前,优化器统计信息在每次服务器重启时以及其他一些操作之后都被清除,并在下一次表访问时重新计算。因此,重新计算统计信息时可能会产生不同的估计值,导致查询执行计划中的选择不同,从而导致查询性能发生变化。

第14.6.12.1.5节“InnoDB持久统计表” 中所述mysql.innodb_table_stats持久性统计信息存储在 mysql.innodb_index_stats表中

要恢复使用非持久性优化器统计信息,可以使用 语句修改表有关相关信息,请参见 第14.6.12.2节“配置非持久性优化器统计参数”ALTER TABLE tbl_name STATS_PERSISTENT=0

14.6.12.1.1配置持久优化器统计的自动统计计算

innodb_stats_auto_recalc 缺省情况下启用配置选项确定当表经历实质性更改(超过10%的行)时是否自动计算统计信息。您还可以使用STATS_AUTO_RECALCa CREATE TABLEALTER TABLE语句中子句 为单个表配置自动统计信息重新计算 innodb_stats_auto_recalc是默认启用的。

由于自动统计信息重新计算(发生在后台)的异步性质,即使innodb_stats_auto_recalc启用了运行影响超过10%表格的DML操作,统计信息也可能不会立即重新计算 在某些情况下,统计数据重新计算可能会延迟几秒钟。如果在更改表的重要部分后立即需要最新的统计信息,请运行ANALYZE TABLE以启动统计信息的同步(前台)重新计算。

如果innodb_stats_auto_recalc 禁用,请在ANALYZE TABLE 对索引列进行重大更改后,通过为每个适用的表发布语句来确保优化程序统计信息的准确性代表性数据加载到表中后,您可以在设置脚本中运行此语句,并且在DML操作显着更改索引列的内容之后定期运行此语句,或者在活动较少时按计划运行。将新索引添加到现有表格时,索引统计信息将被计算并添加到innodb_index_stats表格中,而不考虑其值 innodb_stats_auto_recalc

警告

要确保 在创建新索引时收集统计信息,请启用该 innodb_stats_auto_recalc 选项,或者ANALYZE TABLE在启用持久统计信息模式时创建每个新索引后运行

14.6.12.1.2配置单个表的优化器统计参数

innodb_stats_persistentinnodb_stats_auto_recalc并且 innodb_stats_persistent_sample_pages 是全局配置选项。要覆盖这些系统的设置和配置单个表优化统计参数,你可以定义 STATS_PERSISTENTSTATS_AUTO_RECALCSTATS_SAMPLE_PAGES子句 CREATE TABLEALTER TABLE语句。

  • STATS_PERSISTENT指定是否启用 持续统计为一个InnoDB表。该值DEFAULT导致表的持久统计信息设置由innodb_stats_persistent 配置选项确定 该值为1 表启用持久性统计信息,而值0会关闭此功能。在通过a CREATE TABLEALTER TABLE 语句启用持久性统计ANALYZE TABLE信息后,在将代表性数据加载到表中之后,发出语句来计算统计信息。

  • STATS_AUTO_RECALC指定是否自动重新计算 持续的统计数据InnoDB表。该值DEFAULT导致表的持久统计信息设置由innodb_stats_auto_recalc 配置选项确定 该值1 导致统计信息在表中数据的10%已更改时重新计算。该值0 可防止对此表进行自动重新计算; 在此设置下,ANALYZE TABLE在对表格进行重大更改后,发布重新计算统计数据声明。

  • STATS_SAMPLE_PAGES指定估算索引列的基数和其他统计数据时要采样的索引页数,例如由ANALYZE TABLE

以下CREATE TABLE示例中指定了所有三个子句

CREATE TABLE`t1`(
`id` int(8)NOT NULL auto_increment,
`data` varchar(255),
`日期`日期时间,
PRIMARY KEY(`id`),
INDEX`DATE_IX`(`日期`)
)ENGINE = InnoDB,
  STATS_PERSISTENT = 1,
  STATS_AUTO_RECALC = 1,
  STATS_SAMPLE_PAGES = 25;
14.6.12.1.3配置InnoDB优化器统计的采样页数

MySQL查询优化器使用关于密钥分发的估计 统计信息来根据索引的相对选择性来选择执行计划 的索引。诸如ANALYZE TABLE原因之类的操作InnoDB从表格上的每个索引对随机页面进行采样以估计索引基数(这种技术被称为 随机潜水。)

为了使您能够控制统计估计的质量(从而为查询优化器提供更好的信息),可以使用innodb_stats_persistent_sample_pages可以在运行时设置的参数来更改采样页面的数量

innodb_stats_persistent_sample_pages 默认值为20.作为一般准则,请在遇到以下问题时考虑修改此参数:

  1. 统计信息不够准确,优化程序选择次优计划,如EXPLAIN输出所示 统计的准确性可以通过比较索引的实际基数(通过SELECT DISTINCT在索引列上运行返回 )与mysql.innodb_index_stats持久统计表中提供的估计值来检查

    如果确定统计数据不够准确,innodb_stats_persistent_sample_pages 则应增加数值, 直到统计数据估计足够精确。innodb_stats_persistent_sample_pages 然而,增加 太多会导致 ANALYZE TABLE缓慢运行。

  2. ANALYZE TABLE太慢了在这种情况下 innodb_stats_persistent_sample_pages 应该减少,直到ANALYZE TABLE执行时间可以接受。但是,如果将价值降低太多,可能会导致统计数据不准确和次优查询执行计划的第一个问题。

    如果在准确的统计信息和ANALYZE TABLE执行时间之间无法实现平衡,请考虑减少表中索引列的数量或限制分区数量以降低 ANALYZE TABLE复杂性。因为主键列被附加到每个非唯一索引,所以表的主键列数也很重要。

    有关相关信息,请参见 第14.6.12.3节“估计InnoDB表的ANALYZE TABLE复杂度”

14.6.12.1.4在持续统计计算中包括删除标记的记录

默认情况下,InnoDB在计算统计信息时读取未提交的数据。如果未提交的事务从表中删除行,则 InnoDB排除在计算行估计和索引统计信息时删除标记的记录,这可能会导致针对在表上操作的其他事务的非最佳执行计划使用事务隔离级别以外的 READ UNCOMMITTED为了避免这种情况, innodb_stats_include_delete_marked 可以启用它来确保InnoDB 在计算持久性优化器统计信息时包含删除标记的记录。

innodb_stats_include_delete_marked 启用时,ANALYZE TABLE 重新计算统计数据时,会考虑删除标记的记录。

innodb_stats_include_delete_marked 是影响所有InnoDB的全局设置,并且仅适用于持久性优化器统计信息。

innodb_stats_include_delete_marked 在MySQL 5.7.16中引入。

14.6.12.1.5 InnoDB持久统计表

持久性统计信息功能依赖于mysql数据库中的内部管理表,名为 innodb_table_statsand innodb_index_stats这些表格在所有安装,升级和源代码构建过程中自动设置。

表14.3 innodb_table_stats的列

列名称 描述
database_name 数据库名称
table_name 表名称,分区名称或子分区名称
last_update 指示上次InnoDB 更新此行的时间戳
n_rows 表中的行数
clustered_index_size 主索引的大小,以页为单位
sum_of_other_index_sizes 其他(非主要)索引的总大小,以页为单位

表14.4 innodb_index_stats的列

列名称 描述
database_name 数据库名称
table_name 表名称,分区名称或子分区名称
index_name 索引名称
last_update 指示上次InnoDB 更新此行的时间戳
stat_name 统计的名称,其值在stat_value列中报告
stat_value stat_name 列中命名的统计值的值
sample_size stat_value列中提供的估算抽样的页数
stat_description stat_name列中命名的统计信息的描述

无论是innodb_table_statsinnodb_index_stats表包括一个 last_update示出了当柱 InnoDB最后更新索引的统计,如显示在下面的例子:

MySQL的> SELECT * FROM innodb_table_stats \G
*************************** 1. row ******************** *******
           database_name:sakila
              table_name:actor
             last_update:2014-05-28 16:16:44
                  n_rows:200
    clustered_index_size:1
sum_of_other_index_sizes:1
...
MySQL的> SELECT * FROM innodb_index_stats \G
*************************** 1. row ******************** *******
   database_name:sakila
      table_name:actor
      index_name:PRIMARY
     last_update:2014-05-28 16:16:44
       stat_name:n_diff_pfx01
      stat_value:200
     sample_size:1
     ...

innodb_table_statsinnodb_index_stats表是普通表,可以手动更新。通过手动更新统计信息的功能,可以强制执行特定的查询优化计划或测试备选计划,而无需修改数据库。如果您手动更新统计信息,请发出命令让MySQL重新载入更新后的统计信息。 FLUSH TABLE tbl_name

持久性统计信息被认为是本地信息,因为它们与服务器实例有关。innodb_table_statsinnodb_index_stats表时自动重新计算统计发生,因此不复制。如果运行ANALYZE TABLE 以启动统计信息的同步重新计算,则会复制此语句(除非您禁止对其进行日志记录),并且重新计算将发生在复制从服务器上。

14.6.12.1.6 InnoDB持久统计表示例

innodb_table_stats表格每个表格包含一行。收集的数据将在以下示例中演示。

t1含有伯指数(列 ab)二级索引(列cd),和唯一索引(列e f):

CREATE TABLE t1(
a INT,b INT,c INT,d INT,e INT,f INT,
PRIMARY KEY(a,b),KEY i1(c,d),UNIQUE KEY i2uniq(e,f)
)ENGINE = INNODB;

插入五行样本数据后,表格如下所示:

MySQL的> SELECT * FROM t1;
+ --- + --- + ------ + ------ + ------ + ------ +
| a | b | c | d | e | f |
+ --- + --- + ------ + ------ + ------ + ------ +
| 1 | 1 | 10 | 11 | 100 | 101 |
| 1 | 2 | 10 | 11 | 200 | 102 |
| 1 | 3 | 10 | 11 | 100 | 103 |
| 1 | 4 | 10 | 12 | 200 | 104 |
| 1 | 5 | 10 | 12 | 100 | 105 |
+ --- + --- + ------ + ------ + ------ + ------ +

要立即更新统计信息,请运行ANALYZE TABLE(如果 innodb_stats_auto_recalc已启用,假设已达到更改的表行的10%阈值,则会在几秒钟内自动更新统计信息 ):

MySQL的> ANALYZE TABLE t1;
+ --------- + --------- + ---------- + ---------- +
| 表| 操作| Msg_type | Msg_text |
+ --------- + --------- + ---------- + ---------- +
| test.t1 | 分析| 状态| 好的|
+ --------- + --------- + ---------- + ---------- +

表中的表统计信息t1显示上次InnoDB更新表统计信息(2014-03-14 14:36:34),表()中的行数5,聚集索引大小(1页面)以及其他索引(2页面)的组合大小

MySQL的> SELECT * FROM mysql.innodb_table_stats WHERE table_name like 't1'\G
*************************** 1. row ******************** *******
           database_name:test
              table_name:t1
             last_update:2014-03-14 14:36:34
                  n_rows:5
    clustered_index_size:1
sum_of_other_index_sizes:2

innodb_index_stats表包含每个索引的多行。innodb_index_stats表格中的每一行都提供与列中 所列名称和stat_name列中所述 的特定索引统计信息相关的数据 stat_description例如:

MySQL的> SELECT index_name, stat_name, stat_value, stat_description
       FROM mysql.innodb_index_stats WHERE table_name like 't1';
+ ------------ + -------------- + ------------ + -------- --------------------------- +
| index_name | stat_name | stat_value | stat_description |
+ ------------ + -------------- + ------------ + -------- --------------------------- +
| PRIMARY | n_diff_pfx01 | 1 | a |
| PRIMARY | n_diff_pfx02 | 5 | a,b |
| PRIMARY | n_leaf_pages | 1 | 索引|中的叶子页数
| PRIMARY | 大小| 1 | 索引中的页数|
| i1 | n_diff_pfx01 | 1 | c |
| i1 | n_diff_pfx02 | 2 | c,d |
| i1 | n_diff_pfx03 | 2 | c,d,a |
| i1 | n_diff_pfx04 | 5 | c,d,a,b |
| i1 | n_leaf_pages | 1 | 索引|中的叶子页数
| i1 | 大小| 1 | 索引中的页数|
| i2uniq | n_diff_pfx01 | 2 | e |
| i2uniq | n_diff_pfx02 | 5 | e,f |
| i2uniq | n_leaf_pages | 1 | 索引|中的叶子页数
| i2uniq | 大小| 1 | 索引中的页数|
+ ------------ + -------------- + ------------ + -------- --------------------------- +

stat_name列显示以下类型的统计信息:

  • size:Where stat_name= sizestat_value列显示索引中的页面总数。

  • n_leaf_pages:Where stat_name= n_leaf_pagesstat_value列显示索引中叶页的数量。

  • n_diff_pfxNN:Where stat_name= n_diff_pfx01stat_value列显示索引第一列中不同值的数量。Where stat_name= n_diff_pfx02,该stat_value列显示索引前两列中不同值的数量,以此类推。此外,where stat_name= ,该列显示了一个以逗号分隔的被计数的索引列表。 n_diff_pfxNNstat_description

为了进一步说明 提供基数数据统计量,再次考虑先前引入表格示例。如下所示,该 表是用主索引(列而创建),辅指数(列),和唯一索引(列 ): n_diff_pfxNNt1t1abcdef

CREATE TABLE t1(
  a INT,b INT,c INT,d INT,e INT,f INT,
  PRIMARY KEY(a,b),KEY i1(c,d),UNIQUE KEY i2uniq(e,f)
)ENGINE = INNODB;

插入五行样本数据后,表格如下所示:

MySQL的> SELECT * FROM t1;
+ --- + --- + ------ + ------ + ------ + ------ +
| a | b | c | d | e | f |
+ --- + --- + ------ + ------ + ------ + ------ +
| 1 | 1 | 10 | 11 | 100 | 101 |
| 1 | 2 | 10 | 11 | 200 | 102 |
| 1 | 3 | 10 | 11 | 100 | 103 |
| 1 | 4 | 10 | 12 | 200 | 104 |
| 1 | 5 | 10 | 12 | 100 | 105 |
+ --- + --- + ------ + ------ + ------ + ------ +

当您查询index_namestat_namestat_value,和stat_description在那里 stat_name LIKE 'n_diff%',下面的返回结果集:

MySQL的> SELECT index_name, stat_name, stat_value, stat_description
       FROM mysql.innodb_index_stats
       WHERE table_name like 't1' AND stat_name LIKE 'n_diff%';
+ ------------ + -------------- + ------------ + -------- ---------- +
| index_name | stat_name | stat_value | stat_description |
+ ------------ + -------------- + ------------ + -------- ---------- +
| PRIMARY | n_diff_pfx01 | 1 | a |
| PRIMARY | n_diff_pfx02 | 5 | a,b |
| i1 | n_diff_pfx01 | 1 | c |
| i1 | n_diff_pfx02 | 2 | c,d |
| i1 | n_diff_pfx03 | 2 | c,d,a |
| i1 | n_diff_pfx04 | 5 | c,d,a,b |
| i2uniq | n_diff_pfx01 | 2 | e |
| i2uniq | n_diff_pfx02 | 5 | e,f |
+ ------------ + -------------- + ------------ + -------- ---------- +

对于PRIMARY索引,有两 n_diff%行。行数等于索引中的列数。

注意

对于非唯一索引,InnoDB附加主键的列。

  • 其中 index_name= PRIMARYstat_name= n_diff_pfx01,的stat_value1,这表明存在于索引(列的第一列的单个独特的值 a)。列中的不同值的数量a通过查看a中的列的数据来确认t1,其中存在单个不同的值(1)。计数的列(a)显示在stat_description结果集列中。

  • where index_name= PRIMARY and stat_name= n_diff_pfx02stat_valueis 5,表示索引(a,b的两列中有五个不同的值的不同值的列数ab通过查看在列中的数据证实ab 在表t1,其中有五个不同的值:( ),(1,1),(1,2 1,3),(1,4和)( 1,5)。计数的列(a,b)显示在stat_description结果集列中。

对于二级索引(i1),有n_diff%四行。只为辅助索引(c,d定义了两列,但辅助索引n_diff%四行,因为InnoDB所有非唯一索引都带有主键后缀。因此,有n_diff%四行而不是两个来说明二级索引列(c,d)和主键列(a,b)。

  • 其中index_name= i1stat_name= n_diff_pfx01,的stat_value1,这表明存在于索引(列的第一列的单个独特的值 c)。列中的不同值的数量c通过查看c中的列的数据来确认t1,其中存在单个不同的值:(10)。计数的列(c)显示在stat_description结果集列中。

  • 其中index_name= i1stat_name= n_diff_pfx02stat_valueis 2,它表示索引(c,d的前两列中有两个不同的值通过查看列表中的数据来确认can中的不同值的数量 ,其中有两个不同的值:()和()。计数的列()显示在结果集列中。 dcdt110,1110,12c,dstat_description

  • 其中index_name= i1stat_name= n_diff_pfx03stat_valueis 2,它表示索引(c,d,a)的前三列中有两个不同的值不同的值的列的数量cd以及 a由列查看数据证实cda在表t1,其中有两个不同的值:( 10,11,1和(10,12,1)。计数的列(c,d,a)显示在stat_description结果集列中。

  • 其中index_name= i1stat_name= n_diff_pfx04stat_valueis 5,它表示索引(c,d,a,b的四列中有五个不同的值不同的值的列的数量 cda并且b是通过在列查看数据证实cda,和 b在表t1,其中有五个不同的值:( ),(10,11,1,1),(10,11,1,2),(10,11,1,3 10,12,1,4和(10,12,1,5)。计数的列(c,d,a,b)显示在stat_description结果集列中。

对于唯一索引(i2uniq),有两n_diff%行。

  • 其中 index_name= i2uniqstat_name= n_diff_pfx01stat_valueis 2,表示索引(列e的第一列中有两个不同的值列中的不同值的数量 e通过查看e中的列的数据来确认t1,其中有两个不同的值:(100)和(200)。计数的列(e)显示在stat_description结果集列中。

  • 其中 index_name= i2uniqstat_name= n_diff_pfx02stat_valueis 5表示索引(e,f的两列中有五个不同的值的不同值的列数ef通过查看在列中的数据证实ef 在表t1,其中有五个不同的值:( ),(100,101),(200,102 100,103),(200,104和)( 100,105)。计数的列(e,f)显示在 stat_description 结果集的列。

14.6.12.1.7使用innodb_index_stats表检索索引大小

可以使用innodb_index_stats表格检索表格,分区或子分区的索引大小 在以下示例中,将为表检索索引大小 t1有关表t1和相应索引统计信息的定义 ,请参见 第14.6.12.1.6节“InnoDB持久统计信息表示例”

MySQL的> SELECT SUM(stat_value) pages, index_name,
       SUM(stat_value)*@@innodb_page_size size
       FROM mysql.innodb_index_stats WHERE table_name='t1'
       AND stat_name = 'size' GROUP BY index_name;
+ ------- + ------------ + ------- +
| 页面| index_name | 大小|
+ ------- + ------------ + ------- +
| 1 | PRIMARY | 16384 |
| 1 | i1 | 16384 |
| 1 | i2uniq | 16384 |
+ ------- + ------------ + ------- +

对于分区或子分区,WHERE可以使用具有修改子句的相同查询来检索索引大小。例如,以下查询检索表的分区的索引大小 t1

MySQL的> SELECT SUM(stat_value) pages, index_name,
       SUM(stat_value)*@@innodb_page_size size
       FROM mysql.innodb_index_stats WHERE table_name like 't1#P%'
       AND stat_name = 'size' GROUP BY index_name;

14.6.12.2配置非持久性优化器统计参数

本节介绍如何配置非持久性优化器统计信息。innodb_stats_persistent=OFF当创建或更改单个表 时,优化程序统计信息不会保存到磁盘 STATS_PERSISTENT=0相反,统计信息存储在内存中,并在服务器关闭时丢失。统计数据也会通过某些操作和特定条件定期更新。

从MySQL 5.6.6开始,默认情况下,优化器统计信息将永久保存到磁盘,并由innodb_stats_persistent 配置选项启用 有关持久化优化器统计信息的信息,请参见第14.6.12.1节“配置持久性优化器统计信息参数”

优化器统计信息更新

非持久优化器统计信息在以下情况下更新:

配置采样页面的数量

MySQL查询优化器根据索引的相对选择性使用关于密钥分发的估计 统计信息来为执行计划 选择索引。InnoDB更新优化器统计信息时,它会对来自表上每个索引的随机页面进行采样以估计索引基数(这种技术被称为 随机潜水。)

为了让您能够控制统计估计的质量(从而为查询优化器提供更好的信息),可以使用参数更改采样页面的数量 innodb_stats_transient_sample_pages采样页面的缺省数量是8,这可能不足以产生准确的估计,导致查询优化器选择较差的索引。这种技术对于连接中使用的大型表格和表格尤​​为重要 对这样的表进行不必要的 全表扫描可能是一个重大的性能问题。有关调整此类查询的提示请参见 第8.2.1.19节“避免全表扫描”innodb_stats_transient_sample_pages 是可以在运行时设置的全局参数。

的值 innodb_stats_transient_sample_pages 会影响所有的指数抽样InnoDB 表和索引的时候 innodb_stats_persistent=0当您更改索引样本大小时,请注意以下潜在的重大影响:

  • 像1或2这样的小值可能会导致不准确的基数估计值。

  • 增加该 innodb_stats_transient_sample_pages 值可能需要更多的磁盘读取。大于8(比如100)的值可能会导致打开表格或执行所需时间的显着减速SHOW TABLE STATUS

  • 优化器可能会根据索引选择性的不同估计选择截然不同的查询计划。

无论什么样的价值 innodb_stats_transient_sample_pages 对于一个系统来说都是最好的,设置选项并将其保留在该值。选择一个值,可以对数据库中的所有表格进行合理准确的估计,而无需过多的I / O。因为统计信息会在执行时以外的其他时间自动重新计算 ANALYZE TABLE,所以增加索引样本大小,运行ANALYZE TABLE,然后再次减小样本大小没有任何意义

较小的表格通常比较大的表格需要较少的索引样本。如果你的数据库有很多大表,考虑使用更高的值, innodb_stats_transient_sample_pages 如果你有大多数小表。

14.6.12.3估算InnoDB表的ANALYZE TABLE复杂度

ANALYZE TABLEInnoDB表的复杂性 取决于:

  • 按照定义的采样页数 innodb_stats_persistent_sample_pages

  • 表格中索引列的数量

  • 分区的数量。如果一个表没有分区,则分区的数量被认为是1。

使用这些参数,估算ANALYZE TABLE复杂性的近似公式为

innodb_stats_persistent_sample_pages 索引列的*号表中的*分区数

通常,结果值越大,执行时间就越长ANALYZE TABLE

注意

innodb_stats_persistent_sample_pages 定义在全局级别采样的页面数量。要设置单个表格的采样页数,请使用STATS_SAMPLE_PAGES选项 有关更多信息,请参见第14.6.12.1节“配置持久优化器统计参数”CREATE TABLEALTER TABLE

如果 innodb_stats_persistent=OFF,采样的页数由其定义 innodb_stats_transient_sample_pages有关更多信息,请参见第14.6.12.2节“配置非持久性优化器统计参数”

有关估计ANALYZE TABLE复杂性的更深入的方法,请考虑以下示例。

大O符号中ANALYZE TABLE 复杂度被描述为:

 
O(n样本
  *(n_cols_in_uniq_i
     + n_cols_in_non_uniq_i
     + n_cols_in_pk *(1 + n_non_uniq_i))
  * n_part)          

哪里:

  • n_sample是采样的页数(由其定义 innodb_stats_persistent_sample_pages

  • n_cols_in_uniq_i 是所有唯一索引中所有列的总数(不包括主键列)

  • n_cols_in_non_uniq_i 是所有非唯一索引中所有列的总数

  • n_cols_in_pk是主键中的列数(如果未定义主键, InnoDB则会在内部创建单列主键)

  • n_non_uniq_i 是表中非唯一索引的数量

  • n_part是分区的数量。如果没有定义分区,则该表被认为是单个分区。

现在,请考虑下表(表t),它具有主键(2列),唯一索引(2列)和两个非唯一索引(每个索引各有2列):

CREATE TABLE t(
  INT,
  b INT,
  c INT,
  d INT,
  e INT,
  f INT,
  g INT,
  h INT,
  主键(a,b),
  UNIQUE KEY i1uniq(c,d),
  KEY i2nonuniq(e,f),
  KEY i3nonuniq(g,h)
);

对于上述算法所需的列和索引数据,查询mysql.innodb_index_stats持久索引统计表tn_diff_pfx%统计显示,计数每个索引的列。例如,列 ab主键索引计数。对于非唯一索引,除了用户定义的列以外,还会计算主键列(a,b)。

注意

有关InnoDB 持久统计信息表的更多信息,请参见 第14.6.12.1节“配置持久性优化器统计参数”

MySQL的> SELECT index_name, stat_name, stat_description
       FROM mysql.innodb_index_stats WHERE
       database_name='test' AND
       table_name='t' AND
       stat_name like 'n_diff_pfx%';
  + ------------ + -------------- + ------------------ +
  | index_name | stat_name | stat_description |
  + ------------ + -------------- + ------------------ +
  | PRIMARY | n_diff_pfx01 | a |
  | PRIMARY | n_diff_pfx02 | a,b |
  | i1uniq | n_diff_pfx01 | c |
  | i1uniq | n_diff_pfx02 | c,d |
  | i2nonuniq | n_diff_pfx01 | e |
  | i2nonuniq | n_diff_pfx02 | e,f |
  | i2nonuniq | n_diff_pfx03 | e,f,a |
  | i2nonuniq | n_diff_pfx04 | e,f,a,b |
  | i3nonuniq | n_diff_pfx01 | g |
  | i3nonuniq | n_diff_pfx02 | g,h |
  | i3nonuniq | n_diff_pfx03 | g,h,a |
  | i3nonuniq | n_diff_pfx04 | g,h,a,b |
  + ------------ + -------------- + ------------------ +   

根据上面显示的索引统计数据和表格定义,可以确定以下值:

  • n_cols_in_uniq_i,所有唯一索引中不包括主键列的所有列的总数为2(cd

  • n_cols_in_non_uniq_i,总数在所有非唯一的索引的所有列的,为4( ,e fgh

  • n_cols_in_pk,主键中的列数是2(ab

  • n_non_uniq_i,表中非唯一索引的数量是2(i2nonuniqi3nonuniq))

  • n_part,分区的数量是1。

您现在可以计算 innodb_stats_persistent_sample_pages*(2 + 4 + 2 *(1 + 2))* 1以确定扫描的叶页数。innodb_stats_persistent_sample_pages设置为默认值20,和与16的缺省页大小KiBinnodb_page_size= 16384),则可以预计,20 * 12 * 16384 bytes 被读取为表t,或约4 MiB

注意

所有4个MiB不能从磁盘读取,因为一些叶页可能已经缓存在缓冲池中。

14.6.13为索引页面配置合并阈值

您可以配置MERGE_THRESHOLD索引页值。如果索引页页满百分比低于MERGE_THRESHOLD 删除行时值或行缩短 UPDATE操作时的值,则 InnoDB尝试将索引页与相邻索引页合并。默认 MERGE_THRESHOLD值是50,这是以前的硬编码值。最小值 MERGE_THRESHOLD是1,最大值是50。

索引页面页面已满百分比低于50%(默认 MERGE_THRESHOLD设置)时,会 InnoDB尝试合并索引页面和相邻页面。如果两页都接近50%已满,则在页面合并后不久可能会发生页面拆分。如果这种合并分割行为频繁发生,它可能会对性能产生不利影响。为了避免频繁的合并拆分,您可以降低该MERGE_THRESHOLD值,使 InnoDB尝试页面以较低的页面满百分比进行合并 以较低页面百分比合并页面会在索引页面留出更多空间,并有助于减少合并拆分行为。

MERGE_THRESHOLD索引页面可以为表或个别指标进行定义。MERGE_THRESHOLD为单个索引定义的值在一个优先MERGE_THRESHOLD 的表中定义的值。如果未定义,则该 MERGE_THRESHOLD值默认为50。

为表设置MERGE_THRESHOLD

您可以MERGE_THRESHOLD使用语句子句 来设置例如: table_option COMMENTCREATE TABLE

CREATE TABLE t1(
   id INT,
  KEY id_index(id)
)COMMENT ='MERGE_THRESHOLD = 45';

您还可以MERGE_THRESHOLD使用以下 条款为现有表设置table_option COMMENTALTER TABLE

CREATE TABLE t1(
   id INT,
  KEY id_index(id)
);

ALTER TABLE t1 COMMENT ='MERGE_THRESHOLD = 40';    

为单个索引设置MERGE_THRESHOLD

要设置MERGE_THRESHOLD为单个索引值,则可以使用 与子句,如图所示在以下实施例: index_option COMMENTCREATE TABLEALTER TABLECREATE INDEX

  • MERGE_THRESHOLD使用CREATE TABLE以下命令 设置单个索引

    CREATE TABLE t1(
       id INT,
      KEY id_index(id)COMMENT'MERGE_THRESHOLD = 40'
    );
    
  • MERGE_THRESHOLD使用ALTER TABLE以下命令 设置单个索引

    CREATE TABLE t1(
       id INT,
      KEY id_index(id)
    );
    
    ALTER TABLE t1 DROP KEY id_index;
    ALTER TABLE t1 ADD KEY id_index(id)COMMENT'MERGE_THRESHOLD = 40';
    
  • MERGE_THRESHOLD使用CREATE INDEX以下命令 设置单个索引

    CREATE TABLE t1(id INT);
    CREATE INDEX id_index ON t1(id)COMMENT'MERGE_THRESHOLD = 40';
    
注意

您无法修改MERGE_THRESHOLD索引级别GEN_CLUST_INDEX,这是在创建没有主键或唯一键索引InnoDBInnoDB创建的聚簇索引。您只能通过设置 表格来修改该 MERGE_THRESHOLDGEN_CLUST_INDEXMERGE_THRESHOLD

查询索引的MERGE_THRESHOLD值

MERGE_THRESHOLD索引 的当前值可以通过查询INNODB_SYS_INDEXES获得 例如:

MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_INDEXES WHERE NAME='id_index' \G
*************************** 1. row ******************** *******
       INDEX_ID:91
           名称:id_index
       TABLE_ID:68
           类型:0
       N_FIELDS:1
        PAGE_NO:4
          空间:57
MERGE_THRESHOLD:40

如果使用 子句显式定义,则 可以使用它SHOW CREATE TABLE来查看MERGE_THRESHOLDtable_option COMMENT

MySQL的> SHOW CREATE TABLE t2 \G
*************************** 1. row ******************** *******
       表:t2
创建表:CREATE TABLE`t2`(
  `id` int(11)DEFAULT NULL,
  KEY`id_index`(`id`)COMMENT'MERGE_THRESHOLD = 40'
)ENGINE = InnoDB DEFAULT CHARSET = latin1
注意

MERGE_THRESHOLD在索引级别定义的值在一个优先MERGE_THRESHOLD 的表定义的值。如果未定义,则 MERGE_THRESHOLD默认为50%(MERGE_THRESHOLD=50这是以前的硬编码值。

同样,如果使用 子句明确定义,则可以使用它SHOW INDEX来查看MERGE_THRESHOLD索引index_option COMMENT

MySQL的> SHOW INDEX FROM t2 \G
*************************** 1. row ******************** *******
        表:t2
   Non_unique:1
     Key_name:id_index
 Seq_in_index:1
  Column_name:id
    整理:A
  基数:0
     Sub_part:NULL
       已包装:NULL
         空:是
   Index_type:BTREE
      评论:
Index_comment:MERGE_THRESHOLD = 40

测量MERGE_THRESHOLD设置的效果

INNODB_METRICS表提供了两个计数器,可用于测量 MERGE_THRESHOLD设置对索引页合并的影响。

MySQL的> SELECT NAME, COMMENT FROM INFORMATION_SCHEMA.INNODB_METRICS
       WHERE NAME like '%index_page_merge%';
+ ----------------------------- + ------------------- --------------------- +
| NAME | 评论|
+ ----------------------------- + ------------------- --------------------- +
| index_page_merge_attempts | 索引页合并尝试次数|
| index_page_merge_successful | 成功的索引页合并数|
+ ----------------------------- + ------------------- --------------------- +

在降低MERGE_THRESHOLD价值时,目标是:

  • 少量的页面合并尝试和成功的页面合并

  • 相似数量的页面合并尝试和成功的页面合并

一个MERGE_THRESHOLD设置过小可能会导致大量的数据文件由于空页空间过量。

有关使用INNODB_METRICS计数器的信息 ,请参见 第14.15.6节“InnoDB INFORMATION_SCHEMA度量标准表”

14.7 InnoDB表空间

本节涵盖与InnoDB 表空间相关的主题

14.7.1调整InnoDB系统表空间的大小

本节介绍如何增加或减少InnoDB系统表空间的大小

增加InnoDB系统表空间的大小

增加InnoDB系统表空间大小的最简单方法 是从头开始自动扩展。指定autoextend表空间定义中最后一个数据文件属性。然后InnoDB 在空间不足时以64MB为增量自动增加该文件的大小。增量大小可以通过设置innodb_autoextend_increment 以兆字节度量系统变量的值来更改

您可以通过添加另一个数据文件将系统表空间扩展一个定义的数量:

  1. 关闭MySQL服务器。

  2. 如果前一个数据文件是使用关键字 autoextend定义的,则根据其实际增长的大小将其定义更改为使用固定大小。检查数据文件的大小,将其舍入到1024×1024字节(= 1MB)的最接近倍数,并在中明确指定该舍入大小 innodb_data_file_path

  3. 在结尾添加一个新的数据文件 innodb_data_file_path,可选择使该文件自动扩展。只有最后一个数据文件 innodb_data_file_path可以指定为自动扩展。

  4. 再次启动MySQL服务器。

例如,这个表空间只有一个自动扩展的数据文件 ibdata1

innodb_data_home_dir =
innodb_data_file_path = / ibdata / ibdata1:10M:autoextend

假设这个数据文件随着时间的推移已经增长到了988MB。修改原始数据文件以使用固定大小并添加新的自动扩展数据文件后,以下是配置行:

innodb_data_home_dir =
innodb_data_file_path = / ibdata / ibdata1:988M; / disk2 / ibdata2:50M:autoextend

将新数据文件添加到系统表空间配置时,请确保文件名不引用现有文件。InnoDB在重新启动服务器时创建并初始化文件。

减小InnoDB系统表空间的大小

您不能从系统表空间中删除数据文件。要减小系统表空间大小,请使用以下过程:

  1. 使用mysqldump转储所有 InnoDB表,包括 InnoDB位于MySQL数据库中的表。从5.6开始,InnoDB MySQL数据库中包含五个表格:

    MySQL的> SELECT TABLE_NAME from INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='mysql' and ENGINE='InnoDB';
    + --------------------------- +
    | TABLE_NAME |
    + --------------------------- +
    | engine_cost |
    | gtid_executed |
    | help_category |
    | help_keyword |
    | help_relation |
    | help_topic |
    | innodb_index_stats |
    | innodb_table_stats |
    | 插件|
    | server_cost |
    | 服务器|
    | slave_master_info |
    | slave_relay_log_info |
    | slave_worker_info |
    | time_zone |
    | time_zone_leap_second |
    | time_zone_name |
    | time_zone_transition |
    | time_zone_transition_type |
    + --------------------------- +
    
  2. 停止服务器。

  3. 删除所有现有的表空间文件(*.ibd),包括 ibdataib_log 文件。不要忘记删除*.ibd 位于MySQL数据库中的表的文件。

  4. 删除表格的任何.frm文件 InnoDB

  5. 配置一个新的表空间。

  6. 重新启动服务器。

  7. 导入转储文件。

注意

如果您的数据库仅使用InnoDB引擎,则转储所有 数据库,停止服务器,删除所有数据库和 InnoDB日志文件,重新启动服务器以及导入转储文件可能会更简单

14.7.2更改InnoDB重做日志文件的数量或大小

要更改InnoDB 重做日志文件的数量或大小,请执行以下步骤:

  1. 停止MySQL服务器并确保它关闭而没有错误。

  2. 编辑my.cnf以更改日志文件配置。要更改日志文件大小,请配置 innodb_log_file_size要增加日志文件的数量,请配置 innodb_log_files_in_group

  3. 再次启动MySQL服务器。

如果InnoDB检测到 innodb_log_file_size与重做日志文件大小不同,它会写入日志检查点,关闭并删除旧的日志文件,以请求的大小创建新的日志文件,并打开新的日志文件。

14.7.3将原始磁盘分区用于系统表空间

您可以将原始磁盘分区用作InnoDB 系统表空间中的数据文件 这种技术可以在Windows和某些Linux和Unix系统上启用非缓冲I / O,而无需文件系统开销。使用或不使用原始分区执行测试,以验证此更改是否实际提高了系统的性能。

在使用原始磁盘分区时,请确保运行MySQL服务器的用户标识对该分区具有读写权限。例如,如果以mysql用户身份运行服务器 ,则该分区必须是可读可写的mysql如果使用该--memlock选项运行服务器,则服务器必须运行为root,因此分区必须可读且可写root

下面介绍的过程涉及选项文件修改。有关更多信息,请参见第4.2.6节“使用选项文件”

在Linux和Unix系统上分配原始磁盘分区

  1. 创建新的数据文件时,请在newrawinnodb_data_file_path 选项的数据文件大小之后立即指定关键字 分区必须至少与您指定的大小一样大。请注意,1MB输入InnoDB 是1024×1024字节,而磁盘规格中的1MB通常表示1,000,000字节。

    的[mysqld]
    innodb_data_home_dir =
    innodb_data_file_path中=的/ dev / HDD1:3Gnewraw;的/ dev / HDD2:2Gnewraw
    
  2. 重新启动服务器。InnoDB通知 newraw关键字并初始化新分区。但是,请不要创建或更改任何 InnoDB表格。否则,当您下次重新启动服务器时,请InnoDB重新初始化分区,并且更改将丢失。(作为安全措施, InnoDB防止用户在newraw指定任何分区时修改数据。)

  3. InnoDB初始化新分区后,停止服务器,newraw 将数据文件规范更改raw

    的[mysqld]
    innodb_data_home_dir =
    innodb_data_file_path中=的/ dev / HDD1:3Graw;的/ dev / HDD2:2Graw
    
  4. 重新启动服务器。InnoDB现在允许进行更改。

在Windows上分配原始磁盘分区

在Windows系统上,适用于Linux和Unix系统的相同步骤和相应指导原则适用,只是 innodb_data_file_path在Windows上设置略有不同。

  1. 创建新数据文件时,请newrawinnodb_data_file_path 选项的数据文件大小后立即指定关键字

    的[mysqld]
    innodb_data_home_dir =
    innodb_data_file_path中= //。/ d :: 10Gnewraw
    

    //./对应\\.\于访问物理驱动器的Windows语法在上面的例子中,D:是分区的驱动器号。

  2. 重新启动服务器。InnoDB通知 newraw关键字并初始化新分区。

  3. InnoDB初始化新分区后,停止服务器,newraw 将数据文件规范更改raw

    的[mysqld]
    innodb_data_home_dir =
    innodb_data_file_path中= //。/ d :: 10Graw
    
  4. 重新启动服务器。InnoDB现在允许进行更改。

14.7.4 InnoDB每个表文件的表空间

历史上,所有InnoDB表和索引都存储在系统表空间中这种单一的方法针对的是专门用于数据库处理的机器,精心策划的数据增长,其中任何分配给MySQL的磁盘存储都不会用于其他目的。 每个表InnoDB文件表空间功能提供了更灵活的选择,其中每个InnoDB表及其索引都存储在单独的 .ibd数据文件中。每个这样的 .ibd数据文件代表一个单独的 表空间这个功能由控制 innodb_file_per_table 配置选项,该选项在MySQL 5.6.6及更高版本中默认启用。

文件每表表空间的优点

  • 在截断或删除存储在每个文件表的表空间中的表时,可以回收磁盘空间。截断或删除存储在共享 系统表空间中的表可在系统表空间数据文件(ibdata文件)的内部创建空闲空间,这些文件只能用于新 InnoDB数据。

    同样,ALTER TABLE驻留在共享表空间中的表上的表复制操作可以增加表空间使用的空间量。这些操作可能需要与表中的数据和索引一样多的额外空间。表复制ALTER TABLE操作所需的额外空间 不会释放回操作系统,因为它是针对每个表文件表空间的。

  • TRUNCATE TABLE当存储在文件的每个表tablepaces表运行操作会比较快。

  • 您可以将特定表存储在单独的存储设备上,用于I / O优化,空间管理或备份目的。在以前的版本中,必须将整个数据库目录移动到其他驱动器,并在MySQL数据目录中创建符号链接,如第8.12.3节“使用符号链接”中所述在MySQL 5.6.6及更高版本中,您可以使用语法指定每个表的位置,如第14.7.5节“在数据目录外创建每个文件表空间”中所述CREATE TABLE ... DATA DIRECTORY = absolute_path_to_directory

  • 您可以运行OPTIMIZE TABLE以压缩或重新创建每个文件表的表空间。当您运行OPTIMIZE TABLEInnoDB创建一个新的 .ibd具有临时名称的文件,只使用存储的实际数据所需的空间。优化完成后,InnoDB删除旧.ibd文件并将其替换为新文件。如果以前的.ibd文件显着增长,但实际数据仅占其大小的一部分,则运行OPTIMIZE TABLE可以回收未使用的空间。

  • 您可以移动单个InnoDB表格而不是整个数据库。

  • 您可以将单个InnoDB表从一个MySQL实例复制到另一个(称为可 移动表空间功能)。

  • 以每个文件表格空间创建的表格使用 梭子鱼文件格式。Barracuda文件格式支持 压缩动态行格式等功能。

  • 您可以使用动态行格式为大表BLOB大表启用更高效的存储 TEXT

  • 文件每表的表空间可能会提高成功恢复的几率,并在发生损坏时,服务器无法重新启动或备份和二进制日志不可用时节省时间。

  • 在复制或备份表格时,每个表格文件的表空间便于每个表格的状态报告。

  • 您可以在文件系统级别监视表大小,而无需访问MySQL。

  • 通用Linux文件系统innodb_flush_method设置为 不允许并发写入单个文件 O_DIRECT因此,在使用每个表的文件表空间时,可能会提高性能 innodb_flush_method

  • 系统表空间存储数据字典和撤消日志,并且其大小受InnoDB 表空间大小限制的限制。请参见 第14.8.1.7节“InnoDB表限制”通过每个表文件的表空间,每个表都有其自己的表空间,这为增长空间提供了空间。

文件每表表空间的潜在缺点

  • 对于每个表文件的表空间,每个表可能有未使用的空间,这些空间只能被同一个表的行使用。如果管理不当,这可能会导致浪费空间。

  • fsync操作必须在每个打开的表上运行,而不是在单个文件上运行。由于fsync每个文件都有单独的操作,因此多个表上的写操作不能合并为单个I / O操作。这可能需要 InnoDB执行更高的fsync操作总数

  • mysqld必须为每个表保留一个打开的文件句柄,如果在每个表的文件表空间中有大量表,则这可能会影响性能。

  • 使用更多的文件描述符。

  • innodb_file_per_table在MySQL 5.6.6及更高版本中默认启用。如果向后兼容MySQL 5.5或5.1,你可以考虑禁用它。 重新创建table()的情况下,禁止 innodb_file_per_table 阻止ALTER TABLEInnoDB表从系统表空间移动到单个.ibd文件ALTER TABLEALGORITHM=COPY

    例如,重构InnoDB表格的聚集索引时 ,将使用当前设置重新创建表格 innodb_file_per_table添加或删除InnoDB辅助索引时,此行为不适用 如果在不重建表格的情况下创建辅助索引,则索引与表格数据存储在同一个文件中,而不管当前innodb_file_per_table 设置如何。此行为也不适用于使用CREATE TABLE ... TABLESPACEALTER TABLE ... TABLESPACE语法添加到系统表空间的表 这些表格不受innodb_file_per_table 设置的影响

  • 如果许多表正在增长,则可能会出现更多碎片,从而妨碍DROP TABLE性能和表扫描性能。但是,当管理碎片时,将文件放在其自己的表空间中可以提高性能。

  • 删除每个文件表的表空间时会扫描缓冲池,对于数十GB的缓冲池,这可能需要几秒钟的时间。扫描采用广泛的内部锁执行,这可能会延迟其他操作。系统表空间中的表不受影响。

  • innodb_autoextend_increment 变量定义了用于在自动扩展共享表空间文件变满时扩展其大小的增量大小(以MB为单位)变量不适用于无论innodb_autoextend_increment 设置如何都自动扩展的文件每表表空间文件 最初的扩展是少量的,之后扩展以4MB为增量进行。

14.7.4.1启用和禁用每个文件表的表空间

innodb_file_per_table 选项默认启用。

innodb_file_per_table在启动时设置该 选项,请使用--innodb_file_per_table 命令行选项启动服务器 ,或将此行添加到以下 [mysqld]部分 my.cnf

的[mysqld]
innodb_file_per_table = 1

您也可以innodb_file_per_table 在服务器运行时动态设置

MySQL的> SET GLOBAL innodb_file_per_table=1;

innodb_file_per_table 启用,可以存储InnoDB在一个表 tbl_name.ibd 文件。不同于MyISAM存储引擎,与它的独立 tbl_name.MYDtbl_name.MYI 文件进行索引和数据,InnoDB在一个单一的数据和索引存储在一起 .ibd的文件。tbl_name.frm 文件仍照常创建。

如果innodb_file_per_table在启动选项中禁用 并重新启动服务器,或者使用该SET GLOBAL命令将其禁用 ,则InnoDB 可以在系统表空间内创建新表,除非您已使用该CREATE TABLE ... TABLESPACE选项将表显式地放入每个表的文件表空间或一般表空间中

InnoDB 无论每个文件表的设置如何, 您都可以读写任何表。

要将表从系统表空间移动到其自己的表空间,请更改 innodb_file_per_table设置并重建表:

mysql> SET GLOBAL innodb_file_per_table=1;
mysql>ALTER TABLE table_name ENGINE=InnoDB;

使用CREATE TABLE ... TABLESPACEALTER TABLE ... TABLESPACE语法添加到系统表空间的表 不受innodb_file_per_table设置的影响 要将这些表从系统表空间移动到每个文件表的表空间,必须使用ALTER TABLE ... TABLESPACE语法显式移动它们

注意

InnoDB总是需要系统表空间,因为它将内部数据字典撤消日志放在 那里。这些 .ibd文件不足以进行 InnoDB操作。

当一个表从系统表空间移出到它自己的.ibd文件中时,组成系统表空间的数据文件保持相同的大小。表格以前占用的空间可以重新用于新 InnoDB数据,但不能回收供操作系统使用。将大型 InnoDB表移出系统表空间时,如果磁盘空间有限,则可能希望innodb_file_per_table使用mysqldump命令启用 并重新创建整个实例 如上所述,使用CREATE TABLE ... TABLESPACEALTER TABLE ... TABLESPACE语法添加到系统表空间的表 不受影响 innodb_file_per_table 设置。这些表格必须单独移动。

14.7.5在数据目录之外创建文件每表的表空间

在MySQL数据目录之外的位置创建一个按 文件表的表空间,请使用 语句子句DATA DIRECTORY = absolute_path_to_directoryCREATE TABLE

提前计划位置,因为您不能DATA DIRECTORYALTER TABLE声明中使用 子句 以后更改位置。您指定的目录可能位于具有特定性能或容量特性的其他存储设备上,如快速 SSD或高容量 HDD

在目标目录中,MySQL创建一个与数据库名相对应的子目录,并在其中创建新表.ibd文件在MySQL目录下的数据库 DATADIR目录中,MySQL创建一个table_name.isl 包含表的路径名文件。.isl文件是由MySQL就像一个符号链接处理。使用实际的符号链接从未支持 InnoDB表格。)

以下示例演示了在MySQL数据目录之外创建一个每个文件表的表空间。它显示 .ibd在指定目录中.isl创建文件以及在MySQL数据目录下的数据库目录中创建文件。

MySQL的> USE test;
数据库改变

MySQL的> SHOW VARIABLES LIKE 'innodb_file_per_table';
+ ----------------------- + ------- +
| 变量名| 值|
+ ----------------------- + ------- +
| innodb_file_per_table | ON |
+ ----------------------- + ------- +

MySQL的> CREATE TABLE t1 (c1 INT PRIMARY KEY) DATA DIRECTORY = '/alternative/directory';

#MySQL在相应的子目录中为新表创建一个.ibd文件
#到数据库名称

DB_USER @ Ubuntu的:〜/替代/目录/测试$ ls
t1.ibd

#MySQL创建一个.isl文件,其中包含目录中表的路径名
#在MySQL数据目录下

DB_USER @ Ubuntu的:〜/ MySQL的/数据/测试$ ls
db.opt t1.frm t1.isl

您还可以CREATE TABLE ... TABLESPACE与该DATA DIRECTORY子句结合使用 在MySQL数据目录之外创建一个每个表的文件表空间。为此,您必须指定 innodb_file_per_table为表空间名称。

MySQL的> CREATE TABLE t2 (c1 INT PRIMARY KEY) TABLESPACE = innodb_file_per_table
       DATA DIRECTORY = '/alternative/directory';

innodb_file_per_table使用此方法时 不必启用

使用说明:

  • MySQL最初将.ibd文件保持为打开状态,从而阻止您卸载设备,但如果服务器繁忙,最终可能会关闭表。小心不要在MySQL运行时意外卸载外部设备,或者在设备断开连接时启动MySQL。尝试在关联.ibd文件丢失时访问表 会导致严重错误,需要重新启动服务器。

    如果.ibd 文件仍不在预期路径中,服务器重新启动可能会失败在这种情况下,请手动删除table_name.isl 数据库目录中的 文件,并在重新启动后执行 DROP TABLE删除 .frm文件并从数据字典中删除有关表的 信息

  • 在将表放置在安装了NFS的卷上之前,请查看使用NFS与MySQL中概述的潜在问题

  • 如果使用LVM快照,文件副本或其他基于文件的机制来备份.ibd文件,请始终FLUSH TABLES ... FOR EXPORT首先使用该 语句,以确保在备份发生之前将缓冲在内存中的所有更改 刷新到磁盘。

  • DATA DIRECTORY子句是受支持的使用符号链接的替代方法,不支持单个 InnoDB表。

14.7.6将文件 - 表 - 表 - 表空间复制到另一个实例

本节介绍如何将每个表文件的表 空间从一个MySQL实例复制 到另一个MySQL实例,也称为可传输表空间功能。

有关其他InnoDB表复制方法的信息,请参见第14.8.1.3节“移动或复制InnoDB表”

有很多原因可以将每个InnoDB 文件表 空间复制 到不同的实例:

  • 运行报告而不会在生产服务器上增加额外的负载。

  • 在新的从服务器上为表设置相同的数据

  • 在出现问题或错误后恢复表或分区的备份版本。

  • 作为一种快速移动数据的方式,而不是导入mysqldump命令的结果数据立即可用,而不必重新插入并重建索引。

  • 将每个 文件表的表 空间移动到具有更适合系统要求的存储介质的服务器。例如,您可能希望在SSD设备上拥有繁忙表格,或者在高容量HDD设备上拥有大型表格

限制和使用说明

  • 只有在innodb_file_per_table设置为ON默认设置时才可以执行表空间复制过程 驻留在共享系统表空间中的表不能停顿。

  • 当表停顿时,受影响的表上只允许只读事务。

  • 导入表空间时,页面大小必须与导入实例的页面大小相匹配。

  • DISCARD TABLESPACE不支持与父子时(主键-外键)关系表空间 foreign_key_checks设置为 1在放弃父子表的表空间之前,设置 foreign_key_checks=0分区 InnoDB表不支持外键。

  • ALTER TABLE ... IMPORT TABLESPACE不会对导入的数据实施外键约束。如果表之间存在外键约束,则应该在相同(逻辑)时间点导出所有表。分区 InnoDB表不支持外键。

  • ALTER TABLE ... IMPORT TABLESPACE并且 ALTER TABLE ... IMPORT PARTITION ... TABLESPACE不需要 .cfg元数据文件来导入表空间。但是,导入时没有.cfg文件时不执行元数据检查,并发出类似于以下内容的警告:

    消息:InnoDB:IO读取错误:(2,没有这样的文件或目录)打开'。\
    test \ t.cfg',将尝试导入而没有模式验证
    一排(0.00秒)
    

    .cfg当没有预期的模式不匹配时,无需文件 导入的功能可能会更方便。另外,.cfg无法从.ibd文件中收集元数据的崩溃恢复方案中,无需文件导入的功能 可能很有用

  • 由于.cfg元数据文件的限制,导入分区表的表空间文件时,不会为分区类型或分区定义差异报告模式不匹配。报告列差异。

  • 当运行 ALTER TABLE ... DISCARD PARTITION ... TABLESPACEALTER TABLE ... IMPORT PARTITION ... TABLESPACE在subpartitioned表,无论是分区和子分区表名是允许的。当指定分区名称时,该分区的子分区将包含在该操作中。

  • 如果两个实例都具有GA(通用可用性)状态并且它们的版本在同一个系列中,则从另一个MySQL服务器实例导入表空间文件将起作用。否则,该文件必须已在与其导入的服务器实例相同的服务器实例上创建。

  • 在复制场景中, innodb_file_per_table必须将其设置为ON在主设备和从设备上。

  • 在Windows上,InnoDB以小写形式存储数据库,表空间和表名。为避免在区分大小写的操作系统(如Linux和UNIX)上导入问题,请使用小写名称创建所有数据库,表空间和表。完成此操作的一种便捷方法是在创建数据库,表空间或表之前,将以下行添加到[mysqld] 您的my.cnfmy.ini文件部分

    的[mysqld]
    的lower_case_table_names = 1
    
  • ALTER TABLE ... DISCARD TABLESPACE并且 ALTER TABLE ...IMPORT TABLESPACE不支持属于InnoDB常规表空间的表。有关更多信息,请参阅 CREATE TABLESPACE

  • InnoDB表格 的默认行格式可以使用innodb_default_row_format 配置选项进行 配置。尝试导入未明确定义行格式(ROW_FORMAT或使用 的行)格式的表时,ROW_FORMAT=DEFAULT如果innodb_default_row_format 源实例上的设置与目标实例上的设置不同,则可能会导致模式不匹配错误 有关相关信息,请参见 第14.11.2节“指定表格的行格式”

  • 导出使用InnoDB表空间加密功能加密的 表空间时 ,除了元数据文件外,还会 InnoDB生成一个 文件。对目标实例执行操作之前,必须将该 文件与文件和表空间文件 一起复制到 目标实例。文件包含一个传输密钥和一个加密的表空间密钥。在导入时, 使用传输密钥来解密表空间密钥。有关相关信息,请参见 第14.7.10节“InnoDB表空间加密”.cfp.cfg.cfp.cfgALTER TABLE ... IMPORT TABLESPACE.cfpInnoDB

14.7.6.1可传输的表空间示例

注意

如果要传输使用InnoDB表空间加密进行加密的 表,请参阅 限制和使用说明, 然后再开始获取其他过程信息。

示例1:将InnoDB表复制到另一个实例

此过程演示了如何将常规InnoDB表从正在运行的MySQL服务器实例复制 到另一个正在运行的实例。通过较小的调整,可以使用相同的过程在同一个实例上执行全表恢复。

  1. 在源实例上,创建一个不存在的表:

    mysql> USE test;
    mysql>CREATE TABLE t(c1 INT) ENGINE=InnoDB;
    
  2. 在目标实例上,创建一个不存在的表:

    mysql> USE test;
    mysql>CREATE TABLE t(c1 INT) ENGINE=InnoDB;
    
  3. 在目标实例上,放弃现有的表空间。(在导入表空间之前, InnoDB必须放弃附加到接收表的表空间。)

    MySQL的> ALTER TABLE t DISCARD TABLESPACE;
    
  4. 在源实例上,运行 FLUSH TABLES ... FOR EXPORT以静默表并创建.cfg元数据文件:

    mysql> USE test;
    mysql>FLUSH TABLES t FOR EXPORT;
    

    元数据(.cfg)是在InnoDB数据目录中创建的

    注意

    FLUSH TABLES ... FOR EXPORT从MySQL 5.6.6开始可用。该语句确保对指定表的更改已刷新到磁盘,以便可以在实例运行时创建二进制表副本。FLUSH TABLES ... FOR EXPORT运行时, InnoDB产生了 .cfg在同一个数据库的目录表文件。.cfg文件包含导入表空间文件时用于模式验证的元数据。

  5. .ibd文件和 .cfg元数据文件从源实例复制到目标实例。例如:

    外壳> scp /path/to/datadir/test/t.{ibd,cfg} destination-server:/path/to/datadir/test
    
    注意

    下一步所述,必须在释放共享锁之前复制.ibd文件和 .cfg文件。

  6. 在源实例上,使用 UNLOCK TABLES释放由FLUSH TABLES ... FOR EXPORT以下项获取的锁

    mysql> USE test;
    mysql>UNLOCK TABLES;
    
  7. 在目标实例上,导入表空间:

    mysql> USE test;
    mysql>ALTER TABLE t IMPORT TABLESPACE;
    
    注意

    ALTER TABLE ... IMPORT TABLESPACE功能不会强制导入数据的外键约束。如果表之间存在外键约束,则应该在相同(逻辑)时间点导出所有表。在这种情况下,您将停止更新表,提交所有事务,获取表上的共享锁,然后执行导出操作。

示例2:将InnoDB分区表复制到另一个实例

此过程演示如何将InnoDB正在运行的MySQL服务器实例的分区复制 到另一个正在运行的实例。通过较小的调整,可以使用相同的过程InnoDB在同一实例上执行分区的完整恢复

  1. 在源实例上,创建一个分区表(如果不存在)。在以下示例中,将创建一个包含三个分区(p0,p1,p2)的表格:

    mysql> USE test;
    mysql>CREATE TABLE t1 (i int) ENGINE = InnoDB PARTITION BY KEY (i) PARTITIONS 3;
    

    目录中,这三个分区中的每一个都有一个单独的tablespace()文件。 /datadir/test.ibd

    MySQL的> \! ls /path/to/datadir/test/
    db.opt t1.frm t1#P#p0.ibd t1#P#p1.ibd t1#P#p2.ibd
    
  2. 在目标实例上,创建相同的分区表:

    mysql> USE test;
    mysql>CREATE TABLE t1 (i int) ENGINE = InnoDB PARTITION BY KEY (i) PARTITIONS 3;
    

    目录中,这三个分区中的每一个都有一个单独的tablespace()文件。 /datadir/test.ibd

    MySQL的> \! ls /path/to/datadir/test/
    db.opt t1.frm t1#P#p0.ibd t1#P#p1.ibd t1#P#p2.ibd
    
  3. 在目标实例上,放弃分区表的表空间。(在可以在目标实例上导入表空间之前,必须丢弃附加到接收表的表空间。)

    MySQL的> ALTER TABLE t1 DISCARD TABLESPACE;
    

    .ibd构成分区表的表空间 的三个文件从 目录中被丢弃 ,留下以下文件: /datadir/test

    MySQL的> \! ls /path/to/datadir/test/
    db.opt t1.frm
    
  4. 在源实例上,运行 FLUSH TABLES ... FOR EXPORT静默分区表并创建.cfg元数据文件:

    mysql> USE test;
    mysql>FLUSH TABLES t1 FOR EXPORT;
    

    元数据(.cfg)文件每个表空间(.ibd)文件一个 在源实例目录中创建 /datadir/test

    MySQL的> \! ls /path/to/datadir/test/
    db.opt t1#P#p0.ibd t1#P#p1.ibd t1#P#p2.ibd
    t1.frm t1#P#p0.cfg t1#P#p1.cfg t1#P#p2.cfg
    
    注意

    FLUSH TABLES ... FOR EXPORT语句可确保对指定表的更改已刷新到磁盘,以便可在实例运行时进行二进制表复制。FLUSH TABLES ... FOR EXPORT运行时, InnoDB产生 .cfg在同一数据库的目录表中的表的表空间文件元数据文件。这些.cfg文件包含导入表空间文件时用于模式验证的元数据。 FLUSH TABLES ... FOR EXPORT只能在桌面上运行,而不能在单独的桌面分区上运行。

  5. 复制.ibd.cfg文件从源实例数据库目录复制到目标实例数据库目录。例如:

    壳> SCP /path/to/datadir/test/t1*.{ibd,cfg} destination-server:/path/to/datadir/test
    
    注意

    下一步所述,在释放共享锁之前.ibd.cfg必须复制文件。

  6. 在源实例上,使用 UNLOCK TABLES释放由FLUSH TABLES ... FOR EXPORT以下项获取的锁

    mysql> USE test;
    mysql>UNLOCK TABLES;
    
  7. 在目标实例上,导入分区表的表空间:

    mysql> USE test;
    mysql>ALTER TABLE t1 IMPORT TABLESPACE;
    
示例3:将InnoDB表分区复制到另一个实例

此过程演示如何将InnoDB表分区从正在运行的MySQL服务器实例复制 到另一个正在运行的实例。通过较小的调整,可以使用相同的过程InnoDB在同一个实例上执行表分区恢复 在以下示例中,将在源实例上创建一个包含四个分区(p0,p1,p2,p3)的分区表。两个分区(p2和p3)被复制到目标实例。

  1. 在源实例上,创建一个分区表(如果不存在)。在以下示例中,将创建一个包含四个分区(p0,p1,p2,p3)的表格:

    mysql> USE test;
    mysql>CREATE TABLE t1 (i int) ENGINE = InnoDB PARTITION BY KEY (i) PARTITIONS 4;
    

    在该 目录中,四个分区中的每一个都有一个单独的tablespace()文件。 /datadir/test.ibd

    MySQL的> \! ls /path/to/datadir/test/
    db.opt t1.frm t1#P#p0.ibd t1#P#p1.ibd t1#P#p2.ibd t1#P#p3.ibd
    
  2. 在目标实例上,创建相同的分区表:

    mysql> USE test;
    mysql>CREATE TABLE t1 (i int) ENGINE = InnoDB PARTITION BY KEY (i) PARTITIONS 4;
    

    在该 目录中,四个分区中的每一个都有一个单独的tablespace()文件。 /datadir/test.ibd

    MySQL的> \! ls /path/to/datadir/test/
    db.opt t1.frm t1#P#p0.ibd t1#P#p1.ibd t1#P#p2.ibd t1#P#p3.ibd
    
  3. 在目标实例上,放弃您计划从源实例导入的表空间分区。(在可以在目标实例上导入表空间分区之前,必须丢弃附加到接收表的相应分区。)

    MySQL的> ALTER TABLE t1 DISCARD PARTITION p2, p3 TABLESPACE;
    

    .ibd两个丢弃分区文件将从 目标实例目录中删除 ,并保留以下文件: /datadir/test

    MySQL的> \! ls /path/to/datadir/test/
    db.opt t1.frm t1#P#p0.ibd t1#P#p1.ibd
    
    注意

    ALTER TABLE ... DISCARD PARTITION ... TABLESPACE在子分区表上运行时,分区和子分区表名都是允许的。当指定分区名称时,该分区的子分区将包含在该操作中。

  4. 在源实例上运行 FLUSH TABLES ... FOR EXPORT以暂停分区表并创建.cfg元数据文件。

    mysql> USE test;
    mysql>FLUSH TABLES t1 FOR EXPORT;
    

    元数据文件(.cfg文件) 在源实例目录中创建 有一个 为每个表空间(文件)文件。 /datadir/test.cfg.ibd

    MySQL的> \! ls /path/to/datadir/test/
    db.opt t1#P#p0.ibd t1#P#p1.ibd t1#P#p2.ibd t1#P#p3.ibd
    t1.frm t1#P#p0.cfg t1#P#p1.cfg t1#P#p2.cfg t1#P#p3.cfg
    
    注意

    FLUSH TABLES ... FOR EXPORT语句可确保对指定表的更改已刷新到磁盘,以便可在实例运行时进行二进制表复制。FLUSH TABLES ... FOR EXPORT运行时, InnoDB产生 .cfg在同一数据库的目录表中的表的表空间文件元数据文件。这些.cfg文件包含导入表空间文件时用于模式验证的元数据。 FLUSH TABLES ... FOR EXPORT只能在桌面上运行,而不能在单独的桌面分区上运行。

  5. 复制.ibd.cfg文件从源实例数据库目录复制到目标实例数据库目录。在此示例中,只有 分区2(p2)和分区3(p3)的文件.ibd.cfg文件被复制到data目标实例上的目录。分区0(p0)和分区1(p1)保留在源实例上。

    外壳> scp t1#P#p2.ibd  t1#P#p2.cfg t1#P#p3.ibd t1#P#p3.cfg destination-server:/path/to/datadir/test
    
    注意

    下一步所述,必须在释放共享锁之前复制.ibd文件和 .cfg文件。

  6. 在源实例上,使用 UNLOCK TABLES释放由FLUSH TABLES ... FOR EXPORT以下项获取的锁

    mysql> USE test;
    mysql>UNLOCK TABLES;
    
  7. 在目标实例上,导入表空间分区(p2和p3):

    mysql> USE test;
    mysql>ALTER TABLE t1 IMPORT PARTITION p2, p3 TABLESPACE;
    
    注意

    ALTER TABLE ... IMPORT PARTITION ... TABLESPACE在子分区表上运行时,分区和子分区表名都是允许的。当指定分区名称时,该分区的子分区将包含在该操作中。

14.7.6.2可传输的表空间内部

以下信息描述了常规InnoDB表的可移植表空间复制过程的内部消息和错误日志消息

何时ALTER TABLE ... DISCARD TABLESPACE在目标实例上运行:

  • 该表被锁定在X模式下。

  • 表空间与表分离。

FLUSH TABLES ... FOR EXPORT源实例上运行时:

  • 正在刷新导出的表被锁定在共享模式下。

  • 清除协调程序线程停止。

  • 脏页面被同步到磁盘。

  • 表元数据被写入二进制 .cfg文件。

此操作的预期错误日志消息:

2013-09-24T13:10:19.903526Z 2 [注意] InnoDB:同步到磁盘的“test”。“t”开始。
2013-09-24T13:10:19.903586Z 2 [注] InnoDB:停止清除
2013-09-24T13:10:19.903725Z 2 [Note] InnoDB:将表格元数据写入'./test/t.cfg'
[注意] InnoDB:Table'“test”。“t”'刷新到磁盘
 

UNLOCK TABLES源实例上运行时:

  • 二进制.cfg文件被删除。

  • 正在导入的一个或多个表上的共享锁被释放,清除协调器线程将重新启动。

此操作的预期错误日志消息:

2013-09-24T13:10:21.181104Z 2 [Note] InnoDB:删除元数据文件'./test/t.cfg'
2013-09-24T13:10:21.181180Z 2 [注] InnoDB:恢复清除

ALTER TABLE ... IMPORT TABLESPACE目标实例上运行时,导入算法将为每个正在导入的表空间执行以下操作:

  • 检查每个表空间页面是否存在损坏。

  • 每个页面上的空间ID和日志序列号(LSN)都会更新

  • 标志被验证并且LSN更新为标题页面。

  • Btree页面已更新。

  • 页面状态设置为肮脏,以便将其写入磁盘。

此操作的预期错误日志消息:

2013-07-18 15:15:01 34960 [注意] InnoDB:为从主机'ubuntu'导出的'test / t'表导入表空间,
2013-07-18 15:15:01 34960 [注] InnoDB:第一阶段 - 更新所有页面
2013-07-18 15:15:01 34960 [注] InnoDB:与磁盘同步
2013-07-18 15:15:01 34960 [注意] InnoDB:与磁盘同步 - 完成!
2013-07-18 15:15:01 34960 [注意] InnoDB:第三阶段 - 刷新磁盘变化
2013-07-18 15:15:01 34960 [注] InnoDB:第四阶段 - 刷新完成
注意

您还可能会收到警告,指出表空间被丢弃(如果您放弃了目标表的表空间)并显示一条消息,指出由于缺少.ibd文件而无法计算统计信息

2013-07-18 15:14:38 34960 [Warning] InnoDB:表“test”。“t”表空间被设置为丢弃。
2013-07-18 15:14:38 7f34d9a37700 InnoDB:无法计算表“test”。“t”的统计信息,因为.ibd文件丢失。有关帮助,请参阅
http://dev.mysql.com/doc/refman/5.7/en/innodb-troubleshooting.html

14.7.7配置撤消表空间

撤消日志可能存储在一个或多个撤消表空间中,而不是 系统表空间中此布局与撤消日志驻留在系统表空间中的默认配置不同撤消日志的I / O模式使撤消表空间成为SSD存储的理想候选者 ,同时将系统表空间保留在硬盘存储上。撤消这些表空间内的表空间或单个分段不能被删除。但是,可以截断存储在撤消表空间中的撤消日志。有关更多信息,请参见 第14.7.8节“截断撤消表空间”

要为MySQL实例配置单独的撤消表空间,请执行以下步骤。假定您在将配置部署到生产系统之前正在执行测试实例上的过程。

重要

撤消表空间的数量只能在初始化新的MySQL实例时配置,因为该 innodb_undo_tablespaces选项只能在初始化时设置。指定的设置在MySQL实例的生命周期中是固定的。

注意

innodb_undo_tablespaces 已弃用,将在未来版本中删除。

  1. 使用innodb_undo_directory 配置选项指定撤消表空间的目录位置 如果未指定目录位置,则在MySQL数据目录中创建撤消表空间。

  2. 使用innodb_rollback_segments 配置选项定义回滚段的数量 从相对较低的价值开始,并逐渐增加以检查对性能的影响。默认设置为 innodb_rollback_segments128,这也是最大值。

    一个回滚段总是分配给系统表空间,32个回滚段为临时表空间(ibtmp1保留因此,要分配回滚段来撤消表空间,请将其设置 innodb_rollback_segments为大于33的值。例如,如果您有两个撤消表空间,请将其设置 innodb_rollback_segments为35,以便为两个撤消表空间中的每个分配一个回滚段。回滚段以循环方式分布在撤消表空间中。

    当您配置单独的撤消表空间时,系统表空间中的回滚段将呈现为非活动状态。

  3. 使用该innodb_undo_tablespaces 选项定义撤消表空间的数量 这个设置在MySQL实例的生命周期中是固定的,所以如果你不确定最优值,估计值偏高。

  4. 使用您选择的选项值创建一个新的MySQL测试实例。

  5. 在您的测试实例上使用与您的生产服务器相似的数据量来测试配置。

  6. 基准测试I / O密集型工作负载的性能。

  7. 定期增加innodb_rollback_segments性能测试的价值 并重新运行,直到I / O性能没有进一步改进。

14.7.8截断撤消表空间

要截断撤消表空间,MySQL实例必须配置至少两个撤消表空间。至少两个撤消表空间可确保一个撤消表空间保持活动状态,而另一个撤消表空间将被截断。撤消表空间的数量由innodb_undo_tablespaces选项定义 默认值为0.使用此语句检查以下值 innodb_undo_tablespaces

MySQL的> SELECT @@innodb_undo_tablespaces;
+ --------------------------- +
| @@ innodb_undo_tablespaces |
+ --------------------------- +
| 2 |
+ --------------------------- +
注意

innodb_undo_tablespaces 已弃用,将在未来版本中删除。

有关配置撤消表空间的信息,请参见 第14.7.7节“配置撤消表空间”

启用撤消表空间的截断

要截断撤消表空间,请启用 innodb_undo_log_truncate

MySQL的> SET GLOBAL innodb_undo_log_truncate=ON;

innodb_undo_log_truncate启用时,撤消超过规定的大小限制表空间文件innodb_max_undo_log_size被标记为截断。 innodb_max_undo_log_size是一个动态全局变量,默认值为1024 MiB(1073741824字节)。

MySQL的> SELECT @@innodb_max_undo_log_size;
+ ---------------------------- +
| @@ innodb_max_undo_log_size |
+ ---------------------------- +
| 1073741824 |
+ ---------------------------- +

您可以innodb_max_undo_log_size使用 SET GLOBAL语句进行配置

MySQL的> SET GLOBAL innodb_max_undo_log_size=2147483648;

innodb_undo_log_truncate启用了:

  1. 撤销超过innodb_max_undo_log_size 设置的表空间 被标记为截断。选择用于截断的还原表空间是以循环方式执行的,以避免每次都截断同一个还原表空间。

  2. 驻留在所选撤销表空间中的回滚段将变为非活动状态,以便它们不会分配给新事务。目前正在使用回滚段的现有事务被允许完成。

  3. 净化系统释放那些不再需要的回滚段。

  4. 在撤销表空间中的所有回滚段都被释放后,截断操作将运行并且撤消表空间将被截断为其初始大小。撤消表空间文件的初始大小取决于该 innodb_page_size值。对于默认的16k InnoDB页大小,初始撤消表空间文件大小为10MiB。对于4k,8k,32k和64k页大小,初始撤消表空间文件大小分别为7MiB,8MiB,20MiB和40MiB。

    截断操作后撤消表空间的大小可能会大于初始大小,因为操作完成后会立即使用。

    innodb_undo_directory 选项定义了撤消表空间文件的位置。默认值表示InnoDB默认情况下创建其他日志文件的目录

    MySQL的> SELECT @@innodb_undo_directory;
    + ------------------------- +
    | @@ innodb_undo_directory |
    + ------------------------- +
    | |
    + ------------------------- +
    
  5. 回滚段被重新激活,以便它们可以分配给新的事务。

加快撤销表空间文件的截断

撤消表空间不能被截断,直到其回退段被释放。通常情况下,清除系统每调用一次清除128次就释放一次回滚段。为了加快撤销表空间的截断,可以使用该 innodb_purge_rseg_truncate_frequency 选项临时增加清除系统释放回滚段的频率。默认 innodb_purge_rseg_truncate_frequency 设置是128,这也是最大值。

MySQL的> SELECT @@innodb_purge_rseg_truncate_frequency;
+ ---------------------------------------- +
| @@ innodb_purge_rseg_truncate_frequency |
+ ---------------------------------------- +
| 128 |
+ ---------------------------------------- +

要增加清除线程释放回滚段的频率,请减小 innodb_purge_rseg_truncate_frequency例如:

MySQL的> SET GLOBAL innodb_purge_rseg_truncate_frequency=32;

在线截断撤消表空间文件的性能影响

撤销表空间被截断时,该表空间中的回滚段将暂时停用。其他撤消表空间中剩余的活动回滚段承担整个系统负载的责任,这可能会导致性能下降。性能下降的程度取决于许多因素,包括:

  • 撤消表空间的数量

  • 撤消日志的数量

  • 撤消表空间大小

  • I / O susbsystem的速度

  • 现有长时间运行的交易

  • 系统负载

14.7.9 InnoDB常规表空间

常规表空间是InnoDB 使用CREATE TABLESPACE语法创建的共享表空间本节中的以下主题介绍了常规表空间功能和功能:

一般表空间功能

常规表空间功能提供以下功能:

  • 类似于系统表空间,通用表空间是可以存储多个表的数据的共享表空间。

  • 一般的表空间比文件每表表空间有潜在的内存优势 服务器在内存中保留表空间的元数据。较少的一般表空间中的多个表消耗的表空间元数据的内存少于单独的每个表中的表空间的相同数量的表。

  • 通用表空间数据文件可以放置在相对于或独立于MySQL数据目录的目录中,该目录为您提供了文件每表表空间的许多数据文件和存储管理功能 与文件每表表空间一样,将数据文件放置在MySQL数据目录之外的能力允许您分别管理关键表的性能,为特定表设置RAID或DRBD,或将表绑定到特定磁盘等。

  • 一般的表空间支持Antelope和Barracuda文件格式,因此支持所有的表行格式和相关的功能。通过支持这两种文件格式,常规表空间不依赖于 innodb_file_formatinnodb_file_per_table 设置,这些变量也不会影响常规表空间。

  • TABLESPACE选项可用于 CREATE TABLE在常规表空间,每表文件表空间或系统表空间中创建表。

  • TABLESPACE选项可用于 ALTER TABLE在常规表空间,文件每表表空间和系统表空间之间移动表。以前,无法将表从每个文件表的表空间移动到系统表空间。通过一般的表空间功能,您现在可以做到这一点。

创建一个通用表空间

常规表空间使用CREATE TABLESPACE语法创建

CREATE TABLESPACE tablespace_name
    ADD DATAFILE'file_name'
    [FILE_BLOCK_SIZE =值]
        [ENGINE [=] engine_name]

一般的表空间可以在MySQL数据目录中或在MySQL数据目录之外的目录中创建。为避免与隐式创建的每个表文件表空间冲突,不支持在MySQL数据目录下的子目录中创建常规表空间。另外,在MySQL数据目录之外创建一个通用表空间时,目录必须在创建表空间之前存在。

一个.isl当MySQL数据目录之外创建一个一般的表空间文件在MySQL数据目录中创建。

例子:

在MySQL数据目录中创建一个通用表空间:

MySQL的> CREATE TABLESPACE `ts1` ADD DATAFILE 'ts1.ibd' Engine=InnoDB;

在MySQL数据目录之外的目录中创建一个通用表空间:

MySQL的> CREATE TABLESPACE `ts1` ADD DATAFILE '/my/tablespace/directory/ts1.ibd' Engine=InnoDB;

只要表空间目录不在MySQL数据目录下,就可以指定相对于MySQL数据目录的路径。在这个例子中,该 my_tablespace目录与MySQL数据目录处于同一级别:

MySQL的> CREATE TABLESPACE `ts1` ADD DATAFILE '../my_tablespace/ts1.ibd' Engine=InnoDB;
注意

ENGINE = InnoDB条款必须被定义为的一部分CREATE TABLESPACE语句或InnoDB 必须被定义为默认的存储引擎(default_storage_engine=InnoDB)。

将表添加到常规表空间

创建InnoDB常规表空间后,可以使用向表空间添加表,如以下示例所示: CREATE TABLE tbl_name ... TABLESPACE [=] tablespace_nameALTER TABLE tbl_name TABLESPACE [=] tablespace_name

CREATE TABLE

MySQL的> CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts1 ROW_FORMAT=COMPACT;

ALTER TABLE

MySQL的> ALTER TABLE t2 TABLESPACE ts1;

有关详细的语法信息,请参阅CREATE TABLEALTER TABLE

常规表空间行格式支持

一般的表空间支持所有表行格式(REDUNDANTCOMPACTDYNAMICCOMPRESSED)与压缩和非压缩表不能在同一个表空间一般共存的警告,由于不同的物理页面大小。

对于包含压缩表(ROW_FORMAT=COMPRESSED的常规表空间FILE_BLOCK_SIZE必须指定FILE_BLOCK_SIZE,并且该值必须是与该 值相关的有效压缩页面大小 innodb_page_size另外,压缩表(KEY_BLOCK_SIZE的物理页面大小必须等于 FILE_BLOCK_SIZE/1024例如,如果 innodb_page_size=16KFILE_BLOCK_SIZE=8KKEY_BLOCK_SIZE表格的值必须是8。

下表显示了允许的 innodb_page_sizeFILE_BLOCK_SIZEKEY_BLOCK_SIZE组合。 FILE_BLOCK_SIZE值也可以用字节来指定。要确定KEY_BLOCK_SIZE 给定的有效值FILE_BLOCK_SIZE,请将该 FILE_BLOCK_SIZE值除以1024.表压缩不支持32K和64K InnoDB页面大小。有关更多信息 KEY_BLOCK_SIZE,请参见 CREATE TABLE第14.9.1.2节“创建压缩表”

表14.5压缩表的允许页面大小,FILE_BLOCK_SIZE和KEY_BLOCK_SIZE组合

InnoDB页面大小(innodb_page_size) 允许的FILE_BLOCK_SIZE值 允许的KEY_BLOCK_SIZE值
64K 64K(65536) 压缩不受支持
32K 32K(32768) 压缩不受支持
16K 16K(16384) 不适用:如果innodb_page_size等于 FILE_BLOCK_SIZE,表空间不能包含压缩表。
16K 8K(8192) 8
16K 4K(4096) 4
16K 2K(2048) 2
16K 1K(1024) 1
8K 8K(8192) 不适用:如果innodb_page_size等于 FILE_BLOCK_SIZE,表空间不能包含压缩表。
8K 4K(4096) 4
8K 2K(2048) 2
8K 1K(1024) 1
4K 4K(4096) 不适用:如果innodb_page_size等于 FILE_BLOCK_SIZE,表空间不能包含压缩表。
4K 2K(2048) 2
4K 1K(1024) 1

此示例演示如何创建常规表空间并添加压缩表。该示例假设默认 innodb_page_size值为16K。FILE_BLOCK_SIZE8192要求压缩表有KEY_BLOCK_SIZE8个。

MySQL的> CREATE TABLESPACE `ts2` ADD DATAFILE 'ts2.ibd' FILE_BLOCK_SIZE = 8192 Engine=InnoDB;

MySQL的> CREATE TABLE t4 (c1 INT PRIMARY KEY) TABLESPACE ts2 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;

如果您FILE_BLOCK_SIZE在创建常规表空间时未指定,则 FILE_BLOCK_SIZE默认为 innodb_page_sizeFILE_BLOCK_SIZE等于 innodb_page_size,表空间可能只包含与未压缩的行格式(表COMPACTREDUNDANTDYNAMIC行格式)。

使用ALTER TABLE在表空间之间移动非分区表

您可以使用ALTER TABLETABLESPACE选项将未分区的InnoDB移动 到现有的常规表空间,新的每个文件表表空间或系统表空间。

要将非分区表从每个文件表空间或从系统表空间移动到常规表空间,请指定常规表空间的名称。常规表空间必须存在。查看CREATE TABLESPACE更多信息。

ALTER TABLE tbl_name TABLESPACE [=] tablespace_name

要将非分区表从普通表空间或每个表文件表空间移动到系统表空间,请指定 innodb_system为表空间名称。

ALTER TABLE tbl_name ... TABLESPACE [=] innodb_system

要将非分区表从系统表空间或常规表空间移动到每个文件表表空间,请指定 innodb_file_per_table为表空间名称。

ALTER TABLE tbl_name ... TABLESPACE [=] innodb_file_per_table

ALTER TABLE ... TABLESPACE操作始终会导致完整的表重建,即使该 TABLESPACE属性尚未从其先前的值更改。

ALTER TABLE ... TABLESPACE 语法不支持将表从临时表空间移动到持久表空间。

DATA DIRECTORY条款是允许的, CREATE TABLE ... TABLESPACE=innodb_file_per_table但不支持与该TABLESPACE选项结合使用

常规表空间表分区支持

TABLESPACE选项可用于将单个表分区或子分区分配给 常规表空间,单独的每个表文件表空间或系统表空间。所有分区必须属于同一个存储引擎。以下示例演示了使用情况。

mysql> CREATE TABLESPACE `ts1` ADD DATAFILE 'ts1.ibd' Engine=InnoDB;
mysql>CREATE TABLESPACE `ts2` ADD DATAFILE 'ts2.ibd' Engine=InnoDB;

MySQL的> CREATE TABLE t1 (a INT, b INT) ENGINE = InnoDB
       PARTITION BY RANGE(a) SUBPARTITION BY KEY(b) (
        PARTITION p1 VALUES LESS THAN (100) TABLESPACE=`ts1`,
        PARTITION p2 VALUES LESS THAN (1000) TABLESPACE=`ts2`,
        PARTITION p3 VALUES LESS THAN (10000) TABLESPACE `innodb_file_per_table`,
        PARTITION p4 VALUES LESS THAN (100000) TABLESPACE `innodb_system`);

MySQL的> CREATE TABLE t2 (a INT, b INT) ENGINE = InnoDB
       PARTITION BY RANGE(a) SUBPARTITION BY KEY(b) (
        PARTITION p1 VALUES LESS THAN (100) TABLESPACE=`ts1`
          (SUBPARTITION sp1,
           SUBPARTITION sp2),
        PARTITION p2 VALUES LESS THAN (1000)
          (SUBPARTITION sp3,
           SUBPARTITION sp4 TABLESPACE=`ts2`),
        PARTITION p3 VALUES LESS THAN (10000)
          (SUBPARTITION sp5 TABLESPACE `innodb_system`,
           SUBPARTITION sp6 TABLESPACE `innodb_file_per_table`));

TABLESPACE选项也支持 ALTER TABLE

MySQL的> ALTER TABLE t1 ADD PARTITION (PARTITION p5 VALUES LESS THAN (1000000) TABLESPACE = `ts1`);
注意

如果该选项未定义,则该 操作会将该分区添加到表的默认表空间中,该表空间可以在 or 期间在表级指定TABLESPACE = tablespace_nameALTER TABLE ... ADD PARTITIONCREATE TABLEALTER TABLE

分区操作仅修改表的默认表空间。它不移动表分区。但是,在更改默认表空间后,如果未使用子句明确定义其他表空间,则重建表的操作(如使用操作) 会将分区移至默认表空间ALTER TABLE tbl_name TABLESPACE [=] tablespace_nameALTER TABLEALGORITHM=COPYTABLESPACE [=] tablespace_name

要验证分区是否放置在指定的表空间中,可以查询 INFORMATION_SCHEMA.INNODB_SYS_TABLES

MySQL的> SELECT NAME, SPACE, SPACE_TYPE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES
       WHERE NAME LIKE '%t1%';
+ ----------------------- + ------- + ------------ +
| NAME | SPACE | SPACE_TYPE |
+ ----------------------- + ------- + ------------ +
| test / t1#P#p1#SP#p1sp0 | 57 | 一般|
| test / t1#P#p2#SP#p2sp0 | 58 | 一般|
| test / t1#P#p3#SP#p3sp0 | 59 | 单| |
| test / t1#P#p4#SP#p4sp0 | 0 | 系统|
| test / t1#P#p5#SP#p5sp0 | 57 | 一般|
+ ----------------------- + ------- + ------------ +

MySQL的> SELECT NAME, SPACE, SPACE_TYPE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES
       WHERE NAME LIKE '%t2%';
+ --------------------- + ------- + ------------ +
| NAME | SPACE | SPACE_TYPE |
+ --------------------- + ------- + ------------ +
| test / t2#P#p1#SP#sp1 | 57 | 一般|
| test / t2#P#p1#SP#sp2 | 57 | 一般|
| test / t2#P#p2#SP#sp3 | 60 | 单| |
| test / t2#P#p2#SP#sp4 | 58 | 一般|
| test / t2#P#p3#SP#sp5 | 0 | 系统|
| test / t2#P#p3#SP#sp6 | 61 | 单| |
+ --------------------- + ------- + ------------ +

在表空间之间移动表分区使用ALTER TABLE

要将表分区移动到不同的表空间,必须使用语句移动每个分区ALTER TABLE tbl_name REORGANIZE PARTITION

以下示例演示如何将表分区移动到不同的表空间。 INFORMATION_SCHEMA.INNODB_SYS_TABLES 并被 INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES 查询以验证分区是否放置在预期的表空间中。

注意

如果该选项未在 语句中定义请将分区移至表的默认表空间。在下面的示例中,在表级别定义的表空间是表的默认表空间 分区从系统表空间移动到表空间, 因为分区语句中 没有指定任何选项 TABLESPACE = tablespace_nameREORGANIZE PARTITIONInnoDBts1t1P3ts1TABLESPACEALTER TABLE t1 REORGANIZE PARTITIONP3

如果分区位于不使用子句显式定义的不同表空间中,则 重建表的ALTER TABLE操作(如使用操作) ALGORITHM=COPY将分区移动到默认表空间 TABLESPACE [=] tablespace_name

mysql> CREATE TABLESPACE ts1 ADD DATAFILE 'ts1.ibd';
mysql>CREATE TABLESPACE ts2 ADD DATAFILE 'ts2.ibd';

MySQL的> CREATE TABLE t1 ( a INT NOT NULL, PRIMARY KEY (a))
       ENGINE=InnoDB TABLESPACE ts1                          
       PARTITION BY RANGE (a) PARTITIONS 3 (
        PARTITION P1 VALUES LESS THAN (2),
        PARTITION P2 VALUES LESS THAN (4) TABLESPACE `innodb_file_per_table`,
        PARTITION P3 VALUES LESS THAN (6) TABLESPACE `innodb_system`);


MySQL的> SELECT A.NAME as partition_name, A.SPACE_TYPE as space_type, B.NAME as space_name
       FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES A
       LEFT JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES B
       ON A.SPACE = B.SPACE WHERE A.NAME LIKE '%t1%' ORDER BY A.NAME;
+ ---------------- + ------------ + -------------- +
| partition_name | space_type | space_name |
+ ---------------- + ------------ + -------------- +
| test / t1#P#P1 | 一般| ts1 |
| test / t1#P#P2 | 单| | test / t1#P#P2 |
| test / t1#P#P3 | 系统| NULL |
+ ---------------- + ------------ + -------------- +

MySQL的> ALTER TABLE t1 REORGANIZE PARTITION P1
       INTO (PARTITION P1 VALUES LESS THAN (2) TABLESPACE = `ts2`);
  
MySQL的> ALTER TABLE t1 REORGANIZE PARTITION P2
       INTO (PARTITION P2 VALUES LESS THAN (4) TABLESPACE = `ts2`);
  
MySQL的> ALTER TABLE t1 REORGANIZE PARTITION P3
       INTO (PARTITION P3 VALUES LESS THAN (6));

MySQL的> SELECT A.NAME AS partition_name, A.SPACE_TYPE AS space_type, B.NAME AS space_name
       FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES A
       LEFT JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES B
       ON A.SPACE = B.SPACE WHERE A.NAME LIKE '%t1%' ORDER BY A.NAME;
+ ---------------- + ------------ + ------------ +
| partition_name | space_type | space_name |
+ ---------------- + ------------ + ------------ +
| test / t1#P#P1 | 一般| ts2 |
| test / t1#P#P2 | 一般| ts2 |
| test / t1#P#P3 | 一般| ts1 |
+ ---------------- + ------------ + ------------ +

删除一般表空间

DROP TABLESPACE语句用于删除InnoDB一般表空间。

DROP TABLESPACE操作之前,必须从表空间中删除所有表 如果表空间不为空,则DROP TABLESPACE返回错误。

如果常规表空间DROP TABLESPACE上的操作返回错误,那么表空间可能包含孤立的临时表或中间表,这些表由被服务器出口中断操作留下 有关更多信息,请参见 第14.21.3节“InnoDB数据字典操作故障排除”ALTER TABLE

InnoDB表空间中的最后一个表被删除时,通用表空间不会自动删除。表空间必须使用显式删除 DROP TABLESPACE tablespace_name

一般的表空间不属于任何特定的数据库。一个DROP DATABASE操作可以丢弃属于一般的表空间的表,但它不能删除表空间,即使DROP DATABASE操作下降属于该表空间中的所有表。一般的表空间必须使用明确的删除DROP TABLESPACE tablespace_name

与系统表空间类似,截断或删除存储在通用表空间中的表在通用表空间.ibd数据文件的内部创建空闲空间,该数据文件只能用于新 InnoDB数据。如果在DROP TABLE 操作过程中删除每个文件的表空间,那么空间不会释放回操作系统

这个例子演示了如何删除一个 InnoDB通用的表空间。常规表空间ts1是使用单个表创建的。在删除表空间之前,必须删除该表。

MySQL的> CREATE TABLESPACE `ts1` ADD DATAFILE 'ts1.ibd' Engine=InnoDB;

MySQL的> CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts10 Engine=InnoDB;

MySQL的> DROP TABLE t1;

MySQL的> DROP TABLESPACE ts1;
注意

tablespace_name 是MySQL中区分大小写的标识符。

一般表空间限制

  • 生成的或现有的表空间不能更改为常规表空间。

  • 不支持创建临时常规表空间。

  • 常规表空间不支持临时表。

  • 存储在常规表空间中的表只能在支持常规表空间的MySQL版本中打开。

  • 与系统表空间类似,截断或删除存储在通用表空间中的表在通用表空间.ibd数据文件的内部创建空闲空间,该 数据文件只能用于新InnoDB数据。空间不会释放回操作系统,因为它是用于 每个表文件的表 空间。

    此外,ALTER TABLE驻留在共享表空间(常规表空间或系统表空间)上的表的表复制操作可以增加表空间使用的空间量。这些操作需要与表中的数据和索引一样多的额外空间。表复制ALTER TABLE 操作所需的额外空间不会释放回操作系统,因为它是针对每个表文件表空间的。

  • ALTER TABLE ... DISCARD TABLESPACE并且 ALTER TABLE ...IMPORT TABLESPACE不支持属于常规表空间的表。

有关更多信息,请参见第13.1.19节“CREATE TABLESPACE语法”

14.7.10 InnoDB表空间加密

InnoDB支持InnoDB存储在 每个表文件表 空间中的表的数据加密 此功能为物理表空间数据文件提供静态加密。

InnoDB表空间加密使用由主加密密钥和表空间密钥组成的双层加密密钥体系结构。InnoDB表被加密时,表空间密钥被加密并存储在表空间头部中。当应用程序或经过身份验证的用户想要访问加密的表空间数据时,请InnoDB 使用主加密密钥来解密表空间密钥。表空间密钥的解密版本不会改变,但主加密密钥可根据需要进行更改。此操作被称为主密钥旋转

InnoDB表空间加密功能依赖于一个钥匙圈插件主加密密钥管理。

所有MySQL版本都提供了一个keyring_file 插件,它将主加密密钥数据存储在由keyring_file_data配置选项指定的位置的文件中

警告

InnoDBMySQL的非企业版中表空间加密功能使用该 keyring_file插件进行加密密钥管理。MySQL Enterprise Edition中提供keyring_file插件和 keyring_encrypted_file插件不能作为法规遵从性解决方案。诸如PCI,FIPS和其他安全标准要求使用密钥管理系统来保护,管理和保护密钥库或硬件安全模块(HSM)中的加密密钥。

MySQL企业版提供了keyring_okv插件,其中包括一个KMIP客户端(KMIP 1.1),可与Oracle密钥保险库(OKV)配合使用来提供加密密钥管理。InnoDB表空间加密使用OKV进行加密密钥管理时,该功能被称为 MySQL企业透明数据加密(TDE)

安全和强大的加密密钥管理解决方案(如OKV)对于安全和遵守各种安全标准至关重要。除了其他好处之外,使用密钥保管库可确保密钥安全存储,不会丢失,只有授权的密钥管理员才能知道密钥。密钥库也保持加密密钥的历史记录。

InnoDB表空间加密支持高级加密标准(AES)基于块的加密算法。它使用电子密码本(ECB)块加密模式进行表空间密钥加密和密码块链接(CBC)块加密模式进行数据加密。

有关InnoDB 表空间加密功能的常见问题,请参见 第A.16节“MySQL 5.7 FAQ:InnoDB表空间加密”

InnoDB表空间加密先决条件

  • 密钥环插件(keyring_file插件或keyring_okv插件)必须安装和配置。钥匙扣插件安装在启动时使用该 --early-plugin-load选项执行。早期加载确保插件在InnoDB存储引擎初始化之前可用有关密钥环插件安装和配置说明,请参见第6.5.4节“MySQL密钥环”

    一次只能启用一个密钥环插件。不支持启用多个密钥环插件。

    重要

    一旦在MySQL实例中创建加密表格,创建加密表格时加载的密钥环插件必须--early-plugin-loadInnoDB初始化之前继续使用该选项加载 否则会导致启动时和InnoDB恢复过程中出现错误

    要验证密钥环插件是否处于活动状态,请使用该 SHOW PLUGINS语句或查询 INFORMATION_SCHEMA.PLUGINS 表。例如:

    MySQL的> SELECT PLUGIN_NAME, PLUGIN_STATUS
           FROM INFORMATION_SCHEMA.PLUGINS
           WHERE PLUGIN_NAME LIKE 'keyring%';
    + -------------- + --------------- +
    | PLUGIN_NAME | PLUGIN_STATUS |
    + -------------- + --------------- +
    | keyring_file | ACTIVE |
    + -------------- + --------------- +
    
  • innodb_file_per_table 选项必须启用(默认)。 InnoDB表空间加密仅支持 文件每表的表 空间。或者,您可以TABLESPACE='innodb_file_per_table'在创建加密表或更改现有表以启用加密时指定该 选项。

  • 在对InnoDB生产数据使用表空间加密功能之前,请确保已采取措施防止丢失主加密密钥。如果主加密密钥丢失,则存储在加密表空间文件中的数据将无法恢复。如果您正在使用该 keyring_file插件,建议您在创建第一个加密表后以及在主键旋转之前和之后立即创建密钥环数据文件的备份。密钥环数据文件位置由keyring_file_data 配置选项定义 如果您使用 keyring_okv插件,请确保您已执行必要的操作keyring_okv 插件和Oracle密钥保管库(OKV)配置。对于keyring插件配置,请参见第6.5.4节“MySQL Keyring”有关OKV配置,请参阅Oracle Key Vault站点上提供的OKV文档

启用和禁用InnoDB表空间加密

要为新InnoDB启用加密,请ENCRYPTIONCREATE TABLE语句中指定该选项

MySQL的> CREATE TABLE t1 (c1 INT) ENCRYPTION='Y';

要为现有InnoDB启用加密,请ENCRYPTIONALTER TABLE语句中指定该选项

MySQL的> ALTER TABLE t1 ENCRYPTION='Y';

要禁用InnoDB表的加密,请ENCRYPTION='N'使用 ALTER TABLE

MySQL的> ALTER TABLE t1 ENCRYPTION='N';
注意

使用ENCRYPTION选项更改现有表格时适当地进行规划 ALTER TABLE ... ENCRYPTION操作使用重建表 ALGORITHM=COPYALGORITHM=INPLACE不受支持。

InnoDB表空间加密和主密钥旋转

主密钥应定期轮换,并且每当您怀疑密钥可能已被泄漏时。

主键旋转是原子级的实例级操作。每次旋转主加密密钥时,MySQL实例中的所有表空间密钥都将重新加密并保存回其各自的表空间头文件。作为原子操作,一旦启动旋转操作,重新加密必须对所有表空间键成功。如果主密钥轮换因服务器故障而中断,请InnoDB在服务器重新启动时向前滚动操作。有关更多信息,请参阅InnoDB表空间加密和恢复

旋转主加密密钥仅更改主加密密钥并重新加密表空间密钥。它不解密或重新加密关联的表空间数据。

旋转主加密密钥需要 SUPER特权。

要旋转主加密密钥,请运行:

MySQL的> ALTER INSTANCE ROTATE INNODB MASTER KEY;

ALTER INSTANCE ROTATE INNODB MASTER KEY支持并发DML。但是,它不能同时与运行 CREATE TABLE ... ENCRYPTEDALTER TABLE ... ENCRYPTED作业,并采取锁来防止可能与这些陈述的并发执行出现的冲突。如果其中一个冲突语句正在运行,则必须先完成其他语句才能继续。

InnoDB表空间加密和恢复

如果在主密钥轮换期间发生服务器故障,请 InnoDB在服务器重启时继续执行操作。

在表加密之前安装的密钥环插件必须在存储引擎初始化之前加载,以便在InnoDB初始化和恢复活动访问表空间数据之前,可以从表空间标头中检索解密表空间数据页所需的信息 (请参阅 InnoDB表空间加密先决条件。)

InnoDB初始化和恢复开始,主键旋转操作恢复。由于服务器故障,一些表空间密钥可能已经使用新的主密钥加密。InnoDB 从每个表空间标题读取加密数据,并且如果数据指示使用旧的主加密密钥加密表空间密钥,InnoDB 则从密钥环检索旧密钥并使用它来解密该表空间密钥。InnoDB然后使用新的主加密密钥重新加密表空间密钥,并将重新加密的表空间密钥保存回表空间标头。

导出加密表

导出加密表时,会InnoDB 生成一个用于加密表空间密钥传输密钥。加密的表空间密钥和传输密钥存储在一个 tablespace_name.cfp 文件中。该文件与加密的表空间文件一起执行导入操作。在导入时, InnoDB使用传输密钥来解密tablespace_name.cfp 文件中的表空间密钥 有关相关信息,请参见 第14.7.6节“将文件 - 表 - 表空间复制到另一个实例”

InnoDB表空间加密和复制

识别使用InnoDB表空间加密的表

ENCRYPTION在a CREATE TABLEALTER TABLE语句中指定选项时 ,它被记录在CREATE_OPTIONS字段中 INFORMATION_SCHEMA.TABLES可以查询该字段以识别MySQL实例中的加密表。

MySQL的> SELECT TABLE_SCHEMA, TABLE_NAME, CREATE_OPTIONS FROM INFORMATION_SCHEMA.TABLES
       WHERE CREATE_OPTIONS LIKE '%ENCRYPTION="Y"%';
+ -------------- + ------------ + ---------------- +
| TABLE_SCHEMA | TABLE_NAME | CREATE_OPTIONS |
+ -------------- + ------------ + ---------------- +
| 测试| t1 | ENCRYPTION =“Y”|
+ -------------- + ------------ + ---------------- +

InnoDB表空间加密使用说明

  • 如果服务器在正常操作期间退出或停止,建议使用之前配置的相同加密设置重新启动服务器。

  • 当第一个新的或现有的表被加密时,第一个主加密密钥被生成。

  • 主密钥轮换重新加密表空间密钥,但不会更改表空间密钥本身。要更改表空间密钥,您必须禁用并重新启用表加密 ,这是重建表操作。 ALTER TABLE tbl_name ENCRYPTIONALGORITHM=COPY

  • 如果使用COMPRESSION and ENCRYPTION 选项创建表 ,则在表空间数据加密之前执行压缩。

  • keyring_file 插件使用说明:

    • 如果密钥环数据文件(由keyring_file_data 系统变量命名的文件 )为空或缺失,则首次执行时 ALTER INSTANCE ROTATE INNODB MASTER KEY会创建主加密密钥。

    • 卸载keyring_file插件不会删除现有的密钥环数据文件。

    • 建议您不要将密钥环数据文件放在与表空间数据文件相同的目录下。

    • keyring_file_data 在运行时 修改 系统变量或使用新keyring_file_data 设置重新启动服务器可能导致先前加密的表变得无法访问,从而导致数据丢失。

InnoDB表空间加密限制

  • 高级加密标准(AES)是唯一支持的加密算法。InnoDB表空间加密针对表空间密钥加密和密码块链接(CBC)块加密模式使用电子密码本(ECB)块加密模式进行数据加密。

  • 改变ENCRYPTION一个表属性是一个ALGORITHM=COPY操作。 ALGORITHM=INPLACE不受支持。

  • InnoDB表空间加密仅支持InnoDB存储在每个文件表 空间中的表。存储在其他InnoDB表空间类型(包括常规表空间系统表空间,撤消日志表空间和临时表空间)中的表不支持加密

  • 您无法将加密表从每个文件表表 空间移动或复制 到不受支持的InnoDB 表空间类型。

  • 表空间加密仅适用于表空间中的数据。数据未在重做日志,撤消日志或二进制日志中加密。

  • keyring_file 插件直接迁移keyring_okv插件,反之亦然,目前不受支持。更改密钥环插件需要解密表,卸载当前的密钥环插件,安装和配置其他密钥环插件以及重新加密表。

14.8 InnoDB表和索引

本节涵盖与InnoDB 表格和索引相关的主题

14.8.1 InnoDB表

本节涵盖与InnoDB 表格相关的主题

14.8.1.1创建InnoDB表

要创建一个InnoDB表,请使用该 CREATE TABLE语句。

CREATE TABLE t1(INT,b CHAR(20),PRIMARY KEY(a))ENGINE = InnoDB;

ENGINE=InnoDB 如果InnoDB定义为缺省存储引擎, 不需要指定该子句要检查默认存储引擎,请发出以下语句:

MySQL的> SELECT @@default_storage_engine;
+ -------------------------- +
| @@ default_storage_engine |
+ -------------------------- +
| InnoDB |
+ -------------------------- +

ENGINE=InnoDB如果您计划使用mysqldump或复制来重放CREATE TABLE默认存储引擎所在的服务器上的语句, 您仍然可以使用子句InnoDB

一个InnoDB表及其索引可以在系统表空间文件一个 表表 空间或 一般表空间中创建何时启用 innodb_file_per_table(默认情况下),会InnoDB 在单个每个文件表的表空间中隐式创建一个表。相反, innodb_file_per_table禁用时,会InnoDBInnoDB系统表空间中隐式创建一个要在常规表空间中创建表,请使用 CREATE TABLE ... TABLESPACE语法。有关更多信息,请参见 第14.7.9节“InnoDB常规表空间”

在创建InnoDB表时,MySQL会在MySQL数据目录下的数据库目录中创建一个.frm文件有关.frm文件的更多信息,请参阅 InnoDB表和.frm文件对于在每个表文件表空间中创建的表,MySQL 默认在数据库目录中创建一个 .ibd表空间文件。在创建的表 InnoDB的系统表空间在现有的创建ibdata文件,它驻留在MySQL数据目录。在通用表空间中创建的表是在现有的通用表空间 .ibd文件中创建的一般的表空间文件可以在MySQL数据目录内部或外部创建。有关更多信息,请参见 第14.7.9节“InnoDB常规表空间”

在内部,InnoDB将每个表的条目添加到InnoDB数据字典中。该条目包括数据库名称。例如,如果 t1test 数据库中创建表,则数据库名称的数据字典条目为 'test/t1'这意味着您可以t1在不同的数据库中创建同名()的表,并且表名不会在内部发生冲突 InnoDB

InnoDB表和.frm文件

MySQL将数据字典信息存储在数据库目录中的 .frm文件中。与其他MySQL存储引擎不同, InnoDB它还在系统表空间内的内部数据字典中编码有关该表的信息。当MySQL删除一个表或数据库时,它会删除一个或多个.frm文件以及InnoDB 数据字典中的相应条目InnoDB 仅通过移动.frm文件就无法在数据库之间移动表格 有关移动InnoDB表的信息 ,请参见 第14.8.1.3节“移动或复制InnoDB表”

InnoDB表格和行格式

InnoDB表格 的默认行格式innodb_default_row_format 配置选项定义,该 选项的默认值为 DYNAMICDynamicCompressed 行格式允许您利用 InnoDB表格压缩和长列值的高效离页存储等功能。要使用这些行格式, innodb_file_per_table必须启用(默认为MySQL 5.6.6),并且 innodb_file_format必须设置为梭子鱼

SET GLOBAL innodb_file_per_table = 1;
SET GLOBAL innodb_file_format =梭子鱼;
CREATE TABLE t3(INT,b CHAR(20),PRIMARY KEY(a))ROW_FORMAT = DYNAMIC;
CREATE TABLE t4(INT,b CHAR(20),PRIMARY KEY(a))ROW_FORMAT = COMPRESSED;

或者,您可以使用 CREATE TABLE ... TABLESPACE语法InnoDB在常规表空间中创建 表。常规表空间支持所有行格式。有关更多信息,请参见第14.7.9节“InnoDB常规表空间”

CREATE TABLE t1(c1 INT PRIMARY KEY)TABLESPACE ts1 ROW_FORMAT = DYNAMIC;

CREATE TABLE ... TABLESPACE语法也可用于在系统表空间中创建 InnoDB具有 Dynamic行格式的表格,以及具有CompactRedundant行格式的表格

CREATE TABLE t1(c1 INT PRIMARY KEY)TABLESPACE = innodb_system ROW_FORMAT = DYNAMIC;

有关InnoDB行格式的更多信息,请参见第14.11节“InnoDB行存储和行格式”有关如何确定InnoDB表格的行格式InnoDB 行格式的物理特性,请参见第14.8.1.2节“InnoDB表的物理行结构”

InnoDB表和主键

总是定义一个主键InnoDB,指定一列或多列:

  • 被最重要的查询引用。

  • 永远不要空白。

  • 永远不要有重复的值。

  • 很少,如果曾经插入改变价值。

例如,在包含人员信息的表格中,您不会创建主键,(firstname, lastname)因为不止一个人可以拥有相同的姓名,有的人姓名空白,有时人们更改姓名。有了这么多的约束条件,通常没有明显的一组列用作主键,因此您可以使用数字ID创建一个新列作为主键的全部或一部分。您可以声明 自动增量 列,以便在插入行时自动填充升序值:

#ID的值可以像不同表格中相关项目之间的指针。
CREATE TABLE t5(id INT AUTO_INCREMENT,b CHAR(20),PRIMARY KEY(id));

#主键可以由多个列组成。任何autoinc列必须先到达。
CREATE TABLE t6(id INT AUTO_INCREMENT,INT,b CHAR(20),PRIMARY KEY(id,a));

虽然表格在没有定义主键的情况下工作正常,但主键涉及许多性能方面,并且是任何大型或经常使用的表格的关键设计方面。建议您始终在CREATE TABLE语句中指定主键如果您创建表,加载数据,然后运行ALTER TABLE以稍后添加主键,则该操作比创建表时定义主键慢得多。

查看InnoDB表格属性

要查看InnoDB表格的属性,请发表SHOW TABLE STATUS 声明:

MySQL的> SHOW TABLE STATUS FROM test LIKE 't%' \G;
*************************** 1. row ******************** *******
           名称:t1
         引擎:InnoDB
        版本:10
     Row_format:紧凑
           行数:0
 Avg_row_length:0
    Data_length:16384
Max_data_length:0
   Index_length:0
      Data_free:0
 Auto_increment:NULL
    Create_time:2015-03-16 15:13:31
    Update_time:NULL
     Check_time:NULL
      整理:latin1_swedish_ci
       校验和:NULL
 Create_options:
        评论:
一排(0.00秒)

有关SHOW TABLE STATUS输出的信息,请参见 第13.7.5.36节“SHOW TABLE STATUS语法”

InnoDB表格属性也可以使用InnoDB信息模式系统表查询

MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME='test/t1' \G
*************************** 1. row ******************** *******
     TABLE_ID:45
         NAME:test / t1
         FLAG:1
       N_COLS:5
        空间:35
  FILE_FORMAT:羚羊
   ROW_FORMAT:紧凑
ZIP_PAGE_SIZE:0
   SPACE_TYPE:单一
一排(0.00秒)

有关更多信息,请参见 第14.15.3节“InnoDB INFORMATION_SCHEMA系统表”

14.8.1.2 InnoDB表的物理行结构

表的物理行结构InnoDB取决于创建表时指定的行格式。如果未指定行格式,则使用默认行格式。InnoDB 表格的默认行格式innodb_default_row_format 配置选项定义,该 选项的默认值为 DYNAMIC

以下各节介绍InnoDB行格式的特性

有关InnoDB行格式的更多信息,请参见第14.11节“InnoDB行存储和行格式”

确定InnoDB表的行格式

要确定InnoDB 表格的行格式,请使用SHOW TABLE STATUS例如:

MySQL的> SHOW TABLE STATUS IN test1\G
*************************** 1. row ******************** *******
           名称:t1
         引擎:InnoDB
        版本:10
     Row_format:动态
           行数:0
 Avg_row_length:0
    Data_length:16384
Max_data_length:0
   Index_length:16384
      Data_free:0
 Auto_increment:1
    Create_time:2016-09-14 16:29:38
    Update_time:NULL
     Check_time:NULL
      整理:latin1_swedish_ci
       校验和:NULL
 Create_options: 
        评论: 

您也可以InnoDB通过查询来确定表格 的行格式 INFORMATION_SCHEMA.INNODB_SYS_TABLES

MySQL的> SELECT NAME, ROW_FORMAT FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME='test1/t1';
+ ---------- + ------------ +
| NAME | ROW_FORMAT |
+ ---------- + ------------ +
| test1 / t1 | 动态|
+ ---------- + ------------ +
冗余行格式特征

REDUNDANT格式可用于保持与旧版本MySQL的兼容性。

行中InnoDB使用的表 REDUNDANT行格式具有以下特点:

  • 每个索引记录包含一个6字节的标题。标题用于链接连续的记录,也用于行级锁定。

  • 聚集索引中的记录包含所有用户定义列的字段。另外,还有一个6字节的事务ID字段和一个7字节的滚动指针字段。

  • 如果没有为表定义主键,则每个聚簇索引记录还包含一个6字节的行ID字段。

  • 每个二级索引记录还包含为聚簇索引键定义的所有不在二级索引中的主键字段。

  • 记录包含指向记录每个字段的指针。如果记录中字段的总长度小于128字节,则指针是一个字节; 否则,两个字节。这些指针的数组称为记录目录。这些指针指向的区域称为记录的数据部分。

  • 内部InnoDB存储固定长度字符列,如 CHAR(10)固定长度格式。InnoDB不会从VARCHAR列中截断尾随空格

  • InnoDB将长度大于或等于768字节的固定长度字段编码为可变长度字段,可将其存储在页外。例如,CHAR(255)如果字符集的最大字节长度大于3,则列可能会超过768个字节 utf8mb4

  • SQL NULL值在记录目录中保留一个或两个字节。除此之外,NULL如果存储在可变长度列中,则SQL 值在记录的数据部分中保留零字节。在固定长度的列中,它在记录的数据部分中保留列的固定长度。NULL保留固定空间使得可以将列更新 NULL为非NULL 值,而不会造成索引页的碎片化。

紧凑的行格式特征

COMPACT格式相比,行格式将行存储空间减少了大约20%,但这会 REDUNDANT增加某些操作的CPU使用量。如果您的工作负载是受缓存命中率和磁盘速度限制的典型负载,则 COMPACT格式可能会更快。如果工作负载是一个受CPU速度限制的罕见情况,则紧凑格式可能会变慢。

行中InnoDB使用的表 COMPACT行格式具有以下特点:

  • 每个索引记录都包含一个5字节的标题,其前面可以有一个可变长度的标题。标题用于链接连续的记录,也用于行级锁定。

  • 记录标题的可变长度部分包含一个用于指示NULL的位向量如果索引中的列数可以 NULLN,则位向量占用 字节。(例如,如果有9到16列的任何位置,则位矢量使用两个字节。)列 CEILING(N/8)NULLNULL不要占用这个向量中的位以外的空间。标题的可变长度部分也包含可变长度列的长度。每个长度需要一个或两个字节,具体取决于列的最大长度。如果索引中的所有列都 NOT NULL具有固定长度,则记录标题不包含可变长度部分。

  • 对于每个非NULL可变长度字段,记录标题以一个或两个字节包含列的长度。只有部分列存储在溢出页面的外部或最大长度超过255个字节且实际长度超过127个字节时才需要两个字节。对于外部存储的列,2字节长度表示内部存储部分的长度加上指向外部存储部分的20字节指针。内部部分是768字节,所以长度是768 + 20。20字节的指针存储列的真实长度。

  • 记录头后面是非NULL的数据内容

  • 聚集索引中的记录包含所有用户定义列的字段。另外,还有一个6字节的事务ID字段和一个7字节的滚动指针字段。

  • 如果没有为表定义主键,则每个聚簇索引记录还包含一个6字节的行ID字段。

  • 每个二级索引记录还包含为聚簇索引键定义的所有不在二级索引中的主键字段。如果这些主键字段中的任何一个是可变长度,则每个二级索引的记录标题都有一个可变长度部分来记录它们的长度,即使二级索引是在固定长度列上定义的。

  • 在内部,对于不可变长度字符集, InnoDB存储固定长度字符列(如CHAR(10)固定长度格式)。

    InnoDB不会从VARCHAR 列中截断尾随空格

  • 在内部,对于可变长度字符集(例如 utf8mb3和)utf8mb4InnoDB尝试通过修剪尾部空格字节为单位进行存储 如果 列值的字节长度 超过字节, 则将尾随空格修剪为列值字节长度的最小值。的最大长度 是最大字符字节长度× CHAR(N)NCHAR(N)NInnoDBCHAR(N)N

    InnoDB保留最少的 N字节 在很多情况下保留最小空间可以在不造成索引页碎片的情况下就地完成列更新。通过比较,对于 列占据的最大字符字节长度× CHAR(N)NROW_FORMAT=REDUNDANTCHAR(N)N

    InnoDB将长度大于或等于768字节的固定长度字段编码为可变长度字段,可将其存储在页外。例如,CHAR(255)如果字符集的最大字节长度大于3,则列可能会超过768个字节 utf8mb4

    ROW_FORMAT=DYNAMIC并像 ROW_FORMAT=COMPRESSED处理CHAR存储一样处理 存储ROW_FORMAT=COMPACT

动态和压缩行格式特征

DYNAMICCOMPRESSED 行格式是的变化COMPACT 行格式。有关这些行格式的信息,请参见 第14.11.3节“DYNAMIC和COMPRESSED行格式”

14.8.1.3移动或复制InnoDB表

本节介绍将某些或所有InnoDB移动或复制 到其他服务器或实例的技术。例如,您可能将整个MySQL实例移动到更大,更快的服务器; 您可能会将整个MySQL实例克隆到新的复制从服务器; 您可以将单个表复制到另一个实例以开发和测试应用程序,或者复制到数据仓库服务器以生成报告。

在Windows上,InnoDB始终以小写形式存储数据库和表名。要将数据库以二进制格式从Unix移动到Windows或从Windows移动到Unix,请使用小写名称创建所有数据库和表。完成此操作的一种便捷方法是在创建任何数据库或表之前,将以下行添加到[mysqld]您的my.cnfmy.ini文件部分

的[mysqld]
的lower_case_table_names = 1

移动或复制InnoDB表格的技巧包括:

可移动的表空间

可移动表空间功能用于 FLUSH TABLES ... FOR EXPORT准备InnoDB 表以便从一个服务器实例复制到另一个服务器实例。要使用此功能,InnoDB必须创建表并 innodb_file_per_table设置为 ON使每个InnoDB表都有其自己的表空间。有关使用信息,请参见 第14.7.6节“将每个文件表空间复制到另一个实例”

MySQL企业备份

MySQL企业备份产品可让您备份正在运行的MySQL数据库,同时最大限度地减少操作中断,同时生成数据库的一致快照。当MySQL Enterprise Backup正在复制表时,读取和写入操作可以继续。另外,MySQL Enterprise Backup可以创建压缩备份文件,并备份表的子集。结合MySQL二进制日志,您可以执行时间点恢复。MySQL企业备份包含在MySQL企业订阅中。

有关MySQL企业备份的更多详细信息,请参见 第29.2节“MySQL企业备份概述”

复制数据文件(冷备份方法)

InnoDB只需复制第14.18.1节“InnoDB备份”中 “冷备份”下列出的所有相关文件 即可移动数据库

InnoDB数据和日志文件在具有相同浮点数格式的所有平台上都是二进制兼容的。如果浮点格式不同,但您没有使用 FLOATDOUBLE数据类型,则过程相同:只需复制相关文件即可。

在移动或复制每个.ibd 文件的文件时,源系统和目标系统上的数据库目录名称必须相同。存储在InnoDB共享表空间中的表定义 包括数据库名称。存储在表空间文件中的事务ID和日志序列号在数据库之间也不同。

要将.ibd文件和关联的表从一个数据库移动到另一个数据库,请使用以下RENAME TABLE语句:

RENAME TABLE db1.tbl_nameTO db2.tbl_name;

如果你有一个干净.ibd文件备份 ,你可以将它恢复到源自它的MySQL安装,如下所示:

  1. 自从您复制.ibd文件以来,该表格一定不能被删除或截断,因为这样做会更改存储在表空间内的表格ID。

  2. 发出此ALTER TABLE声明以删除当前.ibd文件:

    ALTER TABLE tbl_nameDISCARD TABLESPACE;
    
  3. 将备份.ibd文件复制到适当的数据库目录。

  4. 发出此ALTER TABLE声明以告诉InnoDB使用.ibd该表的新 文件:

    ALTER TABLE tbl_nameIMPORT TABLESPACE;
    
    注意

    ALTER TABLE ... IMPORT TABLESPACE功能不会强制导入数据的外键约束。

在这种情况下,干净 .ibd 文件备份是满足以下要求的文件备份:

  • .ibd文件中 的交易没有未提交的修改

  • .ibd文件 中没有未合并的插入缓冲区条目

  • 清除已从.ibd文件中删除所有删除标记的索引记录

  • mysqld已经将.ibd文件的所有修改过的页面从缓冲池刷新 到文件中。

您可以.ibd使用以下方法创建一个干净的备份文件:

  1. 停止来自mysqld服务器的所有活动并提交所有事务。

  2. 等待,直到SHOW ENGINE INNODB STATUS显示数据库中没有活动事务,并且InnoDBis 的主线程状态 Waiting for server activity然后你可以制作一个.ibd文件的副本

另一种制作.ibd文件干净副本的方法 是使用MySQL企业备份产品:

  1. 使用MySQL企业备份来备份 InnoDB安装。

  2. 在备份上 启动第二个mysqld服务器,并让它清理备份中的.ibd文件。

导出和导入(mysqldump)

您可以使用mysqldump在一台机器上转储您的表,然后在另一台机器上导入转储文件。使用这种方法,格式是否不同或表中是否包含浮点数据无关紧要。

提高此方法性能的一种方法是在导入数据时关闭 自动提交模式,假定表空间具有足够的空间用于导入事务生成的大回滚段。仅在导入整个表格或表格的一部分后执行提交。

14.8.1.4将表格从MyISAM转换到InnoDB

如果您MyISAM想要将表格转换InnoDB为更好的可靠性和可扩展性,请在转换之前查看以下指南和技巧。

调整MyISAM和InnoDB的内存使用情况

在转换离开MyISAM表格时,降低key_buffer_size配置选项的值 以释放缓存结果不再需要的内存。增加innodb_buffer_pool_size 配置选项的值,该 选项执行类似于为InnoDB分配缓存内存的角色InnoDB 缓冲池可以缓存表数据和索引数据,加快了查询,查找并保持查询结果在内存中进行再利用。有关缓冲池大小配置的指导,请参见 第8.12.4.1节“MySQL如何使用内存”

在繁忙的服务器上,运行关闭查询缓存的基准测试。InnoDB缓冲池提供类似的好处,所以查询缓存可能会不必要地占用内存。有关查询缓存的信息,请参见 第8.10.3节“MySQL查询缓存”

处理太长或太短的交易

因为MyISAM表不支持 事务处理,所以您可能没有太注意 autocommit配置选项和COMMITROLLBACK 语句。这些关键字对于允许多个会话同时读取和写入InnoDB很重要,可在写入繁重的工作负载中提供可观的可伸缩性优势。

在事务处于打开状态时,系统将在事务开始时保留数据快照,如果系统在杂散事务继续运行时插入,更新和删除数百万行,则会导致大量开销。因此,请注意避免长时间运行的交易:

  • 如果您正在使用mysql会话进行交互式实验,请务必 COMMIT(完成更改)或 ROLLBACK(撤消更改)完成。关闭交互式会话,而不是让它们长时间保持打开状态,以避免意外长时间保持交易的开放。

  • 确保应用程序中的任何错误处理程序还包含未 ROLLBACK 完成的更改或COMMIT 已完成的更改。

  • ROLLBACK是一个相对昂贵的操作,因为 INSERTUPDATE和之前的 DELETE操作都写入InnoDB表中 COMMIT,期望大多数更改都成功提交,并且回滚很少。在试验大量数据时,避免对大量行进行更改,然后回滚这些更改。

  • 当使用一系列INSERT语句加载大量数据时 ,请定期 COMMIT检查结果以避免持续几个小时的事务。在数据仓库的典型加载操作中,如果出现问题,则截断表(使用TRUNCATE TABLE)并从头开始,而不是执行 ROLLBACK

上述技巧可以节省在过长的事务中浪费的内存和磁盘空间。当事务比他们应该更短时,问题是过多的I / O。每个 COMMITMySQL都确保每个更改都安全地记录到磁盘上,这涉及到一些I / O。

  • 对于InnoDB桌子上的大多数操作,您应该使用该设置 autocommit=0从效率的角度看,这样就避免了在发出大量连续的不必要的I / O INSERTUPDATEDELETE语句。从安全角度来看,ROLLBACK 如果您在mysql命令行或应用程序中的异常处理程序中犯了错误,则可以发出 语句来恢复丢失或乱码的数据

  • autocommit=1适用于InnoDB表格 的时间运行一系列查询以生成报告或分析统计数据的时间。在这种情况下,不存在与COMMIT相关的I / O损失ROLLBACK,并且InnoDB可以 自动优化只读工作负载

  • 如果您进行了一系列相关更改,请在最后单独完成所有更改 COMMIT例如,如果您将相关信息插入到多个表中,请COMMIT 在完成所有更改后执行一次或者,如果您运行了许多连续的 INSERT语句,请COMMIT在加载完所有数据后执行一个语句 ; 如果你在做数百万条 INSERT语句,可能会通过发行COMMIT每一万条或者十万条记录来分割巨大的交易 ,所以交易不会变得太大。

  • 请记住,即使是SELECT 语句也会打开一个事务,因此在交互式mysql 会话中运行一些报告或调试查询之后,请发出COMMIT 或关闭mysql会话。

处理死锁

您可能会在MySQL错误日志中看到引用死锁 ”的警告消息 ,或者输出 SHOW ENGINE INNODB STATUS尽管名字可怕,但 死锁对于InnoDB表格来说并不是一个严重的问题,并且通常不需要采取任何纠正措施。当两个事务开始修改多个表时,以不同顺序访问表时,它们可以达到每个事务正在等待另一个事务并且两者都不能继续的状态。 启用死锁检测时(默认),MySQL立即检测到这种情况并取消(回滚较小交易,让对方继续。如果使用innodb_deadlock_detect 配置选项禁用死锁检测 ,则InnoDB依赖该 innodb_lock_wait_timeout设置来回滚死锁情况下的事务。

无论哪种方式,您的应用程序都需要错误处理逻辑来重新启动由于死锁而被强制取消的事务。当您重新发布与之前相同的SQL语句时,原始计时问题不再适用。另一个交易已经完成并且您可以继续,或者其他交易仍在进行中,并且您的交易等待完成。

如果经常发生死锁警告,您可以查看应用程序代码以一致的方式对SQL操作进行重新排序,或者缩短事务处理时间。您可以使用innodb_print_all_deadlocks启用选项进行测试, 以查看MySQL错误日志中的所有死锁警告,而不仅仅是SHOW ENGINE INNODB STATUS输出中的最后警告

有关更多信息,请参见第14.5.5节“InnoDB中的死锁”

规划存储布局

为了从InnoDB表中获得最佳性能,您可以调整与存储布局相关的多个参数。

当您将MyISAM是大的,经常访问的,并保持至关重要的数据表,调查和考虑innodb_file_per_tableinnodb_file_format以及 innodb_page_size配置选项,以及 ROW_FORMATKEY_BLOCK_SIZE条款中的 CREATE TABLE说法。

在最初的实验中,最重要的设置是 innodb_file_per_table当启用这个设置时,这是MySQL 5.6.6的默认设置,新的 InnoDB表格将隐式创建在 每个文件表的表 空间中。InnoDB系统表空间相比,每个表文件表空间允许操作系统在截断或删除表时回收磁盘空间。File-per-table表空间还支持 Barracuda文件格式和相关功能,例如表压缩,针对长可变长度列的高效页外存储以及大型索引前缀。有关更多信息,请参见 第14.7.4节“InnoDB文件 - 每个表空间”

您还可以将InnoDB存储在共享的常规表空间中。常规表空间支持梭子鱼文件格式,可以包含多个表。有关更多信息,请参见 第14.7.9节“InnoDB常规表空间”

转换现有表格

转换非InnoDB表使用 InnoDB用途ALTER TABLE

ALTER TABLE table_nameENGINE = InnoDB;
重要

不要转换在MySQL系统表 mysql从数据库MyISAMInnoDB类型。这是一个不受支持的操作。类型。

克隆表结构

您可以创建一个InnoDB表,它是MyISAM表的一个副本,而不是ALTER TABLE用于执行转换,以便在切换之前并行测试旧表和新表。

创建一个InnoDB具有相同列和索引定义的空表。使用看到完整的 语句中使用。将该子句更改SHOW CREATE TABLE table_name\GCREATE TABLEENGINEENGINE=INNODB

传输现有数据

要将大量数据传输到InnoDB如前一节所示创建的空 表中,请插入行INSERT INTO innodb_table SELECT * FROM myisam_table ORDER BY primary_key_columns

InnoDB 插入数据后, 您还可以为表格创建索引历史上,创建新的二级索引对于InnoDB来说是一个缓慢的操作,但是现在,您可以在索引创建步骤中以相对较少的开销加载数据之后创建索引。

如果您UNIQUE对辅助键限制,则可以通过在导入操作过程中暂时关闭唯一性检查来加速表导入:

SET unique_checks = 0;
... import operation ...
SET unique_checks = 1;

对于大型表,这可以节省磁盘I / O,因为 InnoDB可以使用其 更改缓冲区将二级索引记录作为批次写入。确保数据不包含重复的密钥。 unique_checks允许但不要求存储引擎忽略重复密钥。

为了更好地控制插入过程,您可以分片插入大表:

INSERT INTO新建表SELECT * FROM oldtable
   WHERE yourkey> somethingAND yourkey <= somethingelse;

插入所有记录后,您可以重命名表格。

在大表转换期间,增加InnoDB缓冲池的大小 以减少磁盘I / O,最大为物理内存的80%。您还可以增加InnoDB日志文件的大小

存储要求

如果您打算InnoDB在转换过程中表中创建数据的临时数据副本, 建议您以file-per-table表空间创建表,以便在删除表时可以回收磁盘空间。innodb_file_per_table 启用配置选项时(默认),新创建的 InnoDB表格将隐式创建在file-per-table表空间中。

无论您是MyISAM直接转换表还是创建克隆InnoDB表,请确保在此过程中有足够的磁盘空间来保存旧表和新表。 InnoDB表需要比MyISAM更多的磁盘空间 如果ALTER TABLE操作空间不足,则会启动回滚,如果磁盘受限,则可能需要几个小时。对于插入,InnoDB使用插入缓冲区将二级索引记录合并到索引中。这节省了大量的磁盘I / O。对于回滚,不使用这种机制,并且回滚可能比插入长30倍。

在失控回滚的情况下,如果数据库中没有有价值的数据,建议终止数据库进程而不是等待数百万个磁盘I / O操作完成。有关完整的过程,请参见 第14.21.2节“强制InnoDB恢复”

为每个表定义一个主键

PRIMARY KEY子句是影响MySQL查询性能和表和索引空间使用情况的关键因素。主键唯一标识表中的一行。表中的每一行都必须具有主键值,并且没有两行可以具有相同的主键值。

这些是主键的准则,其次是更详细的解释。

  • PRIMARY KEY为每个表 声明一个通常,WHERE查找单个行时,它是您在子句中引用的最重要的列

  • PRIMARY KEY在原始CREATE TABLE 声明中 声明该子句,而不是稍后通过ALTER TABLE声明添加它

  • 仔细选择列及其数据类型。喜欢字符或字符串的数字列。

  • 如果没有使用另一个稳定的,唯一的,非空的数字列,请考虑使用自动增量列。

  • 如果怀疑主键列的值是否可以更改,那么自动增加列也是一个不错的选择。更改主键列的值是一项昂贵的操作,可能涉及重新排列表内和每个二级索引内的数据。

考虑将主键添加到任何尚未拥有主键的表中。根据表格的最大投影尺寸使用最小的实际数字类型。这可以使每行更紧凑,这可以为大型表格节省大量空间。如果表具有任何二级索引则空间节省将成倍增加 ,因为主键值在每个二级索引条目中都会重复。除了减少磁盘上的数据大小外,小型主键还可以让更多数据适合 缓冲池,加快各种操作并提高并发性。

如果表在某些较长的列(例如a)上已经有一个主键VARCHAR,则考虑添加一个新的无符号 AUTO_INCREMENT列并将主键切换为该主键,即使该列未在查询中引用。这种设计更改可以在二级索引中节省大量空间。您可以指定以前的主键列UNIQUE NOT NULL来强制执行与该PRIMARY KEY子句相同的约束,即防止所有这些列出现重复值或空值。

如果您将相关信息分布在多个表中,则通常每个表使用相同的列作为其主键。例如,人事数据库可能有多个表,每个表都有一个员工编号的主键。销售数据库可能包含一些带有客户编号主键的表格,以及其他具有订单编号主键的表格。由于使用主键的查找速度非常快,因此可以为这些表构造高效的连接查询。

如果你PRIMARY KEY完全不用这个子句,MySQL会为你创建一个看不见的东西。这是一个6字节的值,可能比您需要的时间更长,从而浪费空间。因为它是隐藏的,所以你不能在查询中引用它。

应用程序性能考虑

InnoDB需要比等效MyISAM更多的磁盘存储 的可靠性和可扩展性功能 您可以稍微更改列和索引定义,以便更好地利用空间,减少处理结果集时的I / O和内存消耗,以及更有效地使用索引查找的查询优化计划。

如果您为主键设置了数字标识列,请使用该值与任何其他表中的相关值进行交叉引用,特别是对于连接查询。例如,不是接受国家名称作为输入并执行查询搜索相同的名称,而是执行一次查找以确定国家/地区ID,然后执行其他查询(或单个连接查询)在多个表中查找相关信息。而不是将客户或目录项目编号存储为一串数字,可能会占用多个字节,请将其转换为数字标识以存储和查询。一个4字节的无符号数 INT专栏可以索引超过40亿项目(美国的含义为10亿:10亿)。有关不同整数类型的范围,请参见 第11.2.1节“整型(精确值) - INTEGER,INT,SMALLINT,TINYINT,MEDIUMINT,BIGINT”

了解与InnoDB表相关的文件

InnoDB文件比文件需要更多的关心和计划MyISAM

14.8.1.5在InnoDB中处理AUTO_INCREMENT

InnoDB提供了一种可配置的锁定机制,可以显着提高将行添加到具有AUTO_INCREMENT列的表的SQL语句的可伸缩性和性能 要在表中 使用该 AUTO_INCREMENT机制, 必须将列定义为索引的一部分,以便可以在表上执行等效的索引查找以获取最大列值。通常,这是通过将列设置为某个表索引的第一列来实现的。 InnoDBAUTO_INCREMENTSELECT MAX(ai_col)

本节介绍AUTO_INCREMENT锁定模式的行为, 不同AUTO_INCREMENT锁定模式设置的使用含义以及如何InnoDB初始化 AUTO_INCREMENT计数器。

InnoDB AUTO_INCREMENT锁定模式

本节介绍AUTO_INCREMENT用于生成自动增量值锁定模式的行为 以及每种锁定模式如何影响复制。自动增量锁定模式在启动时使用innodb_autoinc_lock_mode 配置参数进行 配置。

以下术语用于描述 innodb_autoinc_lock_mode 设置:

  • INSERT类似 ”的 陈述

    在表中生成新的行中的所有语句,包括INSERTINSERT ... SELECTREPLACEREPLACE ... SELECT,和LOAD DATA包括简单插入批量插入混合模式 插入。

  • 简单插入

    可以预先确定要插入的行数的语句(最初处理语句时)。这包括单行和多行 INSERT以及 REPLACE没有嵌套子查询但没有的语句 INSERT ... ON DUPLICATE KEY UPDATE

  • 批量插入

    预先不知道要插入的行数(以及所需自动增量值的数量)的语句。这包括 INSERT ... SELECTREPLACE ... SELECTLOAD DATA声明,但不是简单的 INSERT在处理每一行时,一次为列InnoDB 分配新的值 AUTO_INCREMENT

  • 混合模式插入

    这些是简单插入语句,用于为新行的某些(但不是全部)行指定自动递增值。下面c1是一个例子,其中 是一 AUTO_INCREMENT列表格 t1

    INSERT INTO t1(c1,c2)VALUES(1,'a'),(NULL,'b'),(5,'c'),(NULL,'d');
    

    另一种类型的混合模式插入INSERT ... ON DUPLICATE KEY UPDATE,在最坏的情况下,INSERT 其后是a UPDATE,其中AUTO_INCREMENT在更新阶段期间可能或不可能使用列的分配值

innodb_autoinc_lock_mode 配置参数 有三种可能的设置 对于传统连续交错锁定模式,设置分别为0,1或2

  • innodb_autoinc_lock_mode = 0传统锁定模式)

    传统的锁定模式提供了与innodb_autoinc_lock_mode 在MySQL 5.1中引入配置参数之前相同的行为 传统的锁定模式选项提供了向后兼容性,性能测试和解决“混合模式插入”的问题,这是由于可能的语义差异。

    在这种锁定模式下,所有INSERT-like 语句都会获得一个特殊的表级 AUTO-INC锁,用于插入带有AUTO_INCREMENT列的表中。通常将该锁保持在语句的末尾(而不是结束事务),以确保自动递增值以给定INSERT语句序列的可预测和可重复的顺序进行分配 ,并确保自动递增值由任何给定的语句分配都是连续的。

    在基于语句的复制的情况下,这意味着在从属服务器上复制SQL语句时,自动增量列将使用与主服务器上相同的值。执行多条INSERT语句的结果是确定性的,并且从设备复制与主设备上相同的数据。如果由多个INSERT语句生成的自动递增值被交错,那么两个并发INSERT语句的结果 将是不确定的,并且不能可靠地使用基于语句的复制传播到从属服务器。

    为了清楚说明,请考虑使用此表的示例:

    CREATE TABLE t1(
      c1 INT(11)NOT NULL AUTO_INCREMENT,
      c2 VARCHAR(10)DEFAULT NULL,
      主键(c1)
    )ENGINE = InnoDB;
    

    假设有两个事务正在运行,每个事务都将行插入带有AUTO_INCREMENT的表中 一个事务使用INSERT ... SELECT插入1000行语句,另一个事务使用 插入一行的简单 INSERT语句:

    Tx1:INSERT INTO t1(c2)从另一个表中选择1000行...
    Tx2:INSERT INTO t1(c2)VALUES('xxx');
    

    InnoDB无法预先知道从Tx1 SELECT中的 INSERT语句中检索了多少行 ,并且随着语句的进行一次一个地分配自动递增值。通过在表达式末尾保存一个表级锁,每次只能执行一个 INSERT引用表的语句t1,并且不会交错由不同语句产生的自增号。由Tx1 INSERT ... SELECT语句生成的自动递增值 是连续的,并且由()使用的(单个)自动递增值 INSERT在Tx2中的语句要么小于要么大于用于Tx1的所有语句,这取决于哪个语句首先执行。

    只要从二进制日志(使用基于语句的复制或恢复场景中)重播时SQL语句以相同顺序执行,结果与第一次运行Tx1和Tx2时的结果相同。因此,表级锁一直持续到语句结束时INSERT 使用自动增量安全来使用基于语句的复制。但是,当多个事务同时执行插入语句时,这些表级锁会限制并发性和可伸缩性。

    在前面的示例中,如果没有表级锁定,则INSERTTx2中使用的自动增量列的值 取决于执行语句的时间。如果 INSERTTx2在INSERTTx1运行时(而不是在它开始之前或完成之后)执行,则由两个INSERT语句分配的特定自动递增值是非确定性的,并且可能因运行而异。

    连续 锁定模式下,InnoDB可以避免对预先知道行数的简单插入语句使用表级AUTO-INC,并且仍然保留基于语句的复制的确定性执行和安全性。

    如果您没有使用二进制日志重播SQL语句作为恢复或复制的一部分, 则可以使用交叉锁定模式来消除对表级AUTO-INC锁定的所有使用, 以实现更高的并发性和性能,代价是允许自动分离 - 由语句分配的增量编号,并且可能通过并行执行语句交错分配编号。

  • innodb_autoinc_lock_mode = 1连续锁定模式)

    这是默认的锁定模式。在这种模式下,批量插入使用特殊的 AUTO-INC表级锁,并保持它直到语句结束。这适用于所有 INSERT ... SELECTREPLACE ... SELECTLOAD DATA语句。一次AUTO-INC只能执行一个持有该锁的语句 如果大容量插入操作的源表与目标表不同,则AUTO-INC 在从源表中选择的第一行执行共享锁后,将对目标表执行锁定。如果批量插入操作的源和目标是同一个表,AUTO-INC在对所有选定行进行共享锁定之后进行锁定。

    简单插入(预先知道要插入的行数)AUTO-INC通过在互斥体(轻量级锁)的控制下获得所需数量的自动增量值来避免表级 锁定在分配过程的持续时间内保持, 直到语句完成。AUTO-INC除非AUTO-INC另一个事务持有锁,否则不使用表级如果另一个事务持有一个 AUTO-INC锁,一个简单插入等待AUTO-INC 锁,就好像它是一个批量插入

    这种锁定模式可以确保在出现INSERT预先未知行数语句的情况下 (以及在语句进行时自动递增数字的位置),所有由INSERT类似 语句指定的自动递增值 都是连续的,操作对于基于语句的复制是安全的。

    简而言之,这种锁定模式显着提高了可扩展性,同时可以安全地使用基于语句的复制。此外,与传统 锁定模式一样,任何给定语句分配的自动递增数字都是连续的没有变化在语义比较 传统对于使用自动递增,有一个重要的例外,任何声明模式。

    混合模式插入 例外,其中用户为AUTO_INCREMENT多行简单插入 ”中的某些行(但不是全部)的行提供显式值 对于这样的插入,InnoDB分配比要插入的行数更多的自动增量值。但是,自动分配的所有值都会连续生成(并因此高于)最近执行的前一个语句生成的自动递增值。超额号码丢失。

  • innodb_autoinc_lock_mode = 2交错锁定模式)

    在这种锁定模式下,没有 INSERT-like 语句使用表级AUTO-INC 锁定,并且可以同时执行多个语句。这是最快和最可伸缩的锁定模式,但当从二进制日志中重播SQL语句时,使用基于语句的复制或恢复方案时,这种方式并不安全

    在此锁定模式下,自动递增值保证在所有同时执行的INSERT类似 语句中是唯一且单调递增的 但是,由于多个语句可能同时生成数字(也就是说,数字的分配是跨越语句交错的),所以为任何给定语句插入的行生成的值可能不连续。

    如果执行的唯一语句是提前知道要插入的行数的简单插入,则除了混合模式插入外,对于单个语句生成的数字没有间隔 但是,执行 批量插入 ”时,可能会有由任何给定语句分配的自动递增值中的空白。

InnoDB AUTO_INCREMENT锁模式使用含义
  • 在复制时使用自动增量

    如果您正在使用基于语句的复制,请将其设置 innodb_autoinc_lock_mode 为0或1,并在主服务器及其从服务器上使用相同的值。如果您使用innodb_autoinc_lock_mode = 2(interleaved)或者主设备和从设备不使用相同锁定模式的配置,则自动递增值不能保证在主设备上与主设备上 的相同。

    如果您使用的是基于行或混合格式的复制,则所有自动增量锁定模式都是安全的,因为基于行的复制对SQL语句的执行顺序不敏感(并且混合格式使用基于行的复制任何对基于语句的复制不安全的语句)。

  • 丢失自动递增值和序列差距

    在所有锁定模式(0,1和2)中,如果生成自动递增值的事务回退,那些自动递增值将丢失一旦为自动增量列生成值,无论是否 INSERT类似 语句完成,以及是否回滚包含的事务,都无法回滚它。这些丢失的值不会被重复使用。因此,AUTO_INCREMENT表格列中存储的值可能存在间隙

  • AUTO_INCREMENT指定NULL或0

    在所有的锁模式(0,1,2),如果用户指定NULL或0用于AUTO_INCREMENT在列INSERTInnoDB将行仿佛没有指定值,并且生成用于它的新值。

  • AUTO_INCREMENT指定一个负值

    在所有锁定模式(0,1和2)中,如果为AUTO_INCREMENT指定负值,则不会定义自动递增机制的行为

  • 如果该AUTO_INCREMENT值变得大于指定整数类型的最大整数

    在所有锁定模式(0,1和2)中,如果值大于可以存储在指定整数类型中的最大整数,则自动递增机制的行为未定义。

  • 批量插入 ”的 自动增量值的间隔

    innodb_autoinc_lock_mode 设定为0(传统)或1(连续),通过任何给定语句生成的自动递增的值是连续的,没有间隙,这是因为表级AUTO-INC 锁一直保持到该语句的末尾,只有一个这样的陈述可以一次执行。

    innodb_autoinc_lock_mode 设置为2(交织),有可能是在所产生的自动递增值间隙批量插入, ”但只有当有同时执行的 INSERT 的语句。

    对于锁定模式1或2,连续的语句之间可能会出现间隙,因为对于批量插入,每个语句所需的自动递增值的确切数量可能不知道,并且可能会高估。

  • 自动增加由混合模式插入指定的值

    考虑一个混合模式插入,其中 简单插入指定一些(但不是全部)结果行的自动增量值。这种语句在锁定模式0,1和2中表现不同。例如,假设c1AUTO_INCREMENT表格的t1,并且最近自动生成的序列号是100。

    mysql> CREATE TABLE t1 (
        - > c1 INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 
        - > c2 CHAR(1)
        - >) ENGINE = INNODB;
    

    现在,考虑下面的混合模式插入语句:

    MySQL的> INSERT INTO t1 (c1,c2) VALUES (1,'a'), (NULL,'b'), (5,'c'), (NULL,'d');
    

    随着 innodb_autoinc_lock_mode 设置为0(传统),这四个新的行是:

    MySQL的> SELECT c1, c2 FROM t1 ORDER BY c2;
    + ----- + ------ +
    | c1 | c2 |
    + ----- + ------ +
    | 1 | a |
    | 101 | b |
    | 5 | c |
    | 102 | d |
    + ----- + ------ +
    

    下一个可用自动递增值为103,因为自动递增值一次分配一次,而不是在语句执行开始时一次全部分配。这个结果是真实的是否有并发执行 INSERT (任何类型的)陈述。

    随着 innodb_autoinc_lock_mode 设置为1(连续),这四个新行也:

    MySQL的> SELECT c1, c2 FROM t1 ORDER BY c2;
    + ----- + ------ +
    | c1 | c2 |
    + ----- + ------ +
    | 1 | a |
    | 101 | b |
    | 5 | c |
    | 102 | d |
    + ----- + ------ +
    

    但是,在这种情况下,下一个可用自动递增值是105,而不是103,因为在处理语句时分配了四个自动递增值,但只使用了两个。这个结果是真实的是否有并发执行 INSERT (任何类型的)陈述。

    innodb_autoinc_lock_mode 设定为模式2(交织),四个新的行是:

    MySQL的> SELECT c1, c2 FROM t1 ORDER BY c2;
    + ----- + ------ +
    | c1 | c2 |
    + ----- + ------ +
    | 1 | a |
    |   x| b |
    | 5 | c |
    |   y| d |
    + ----- + ------ +
    

    值和xy是唯一的,比以前生成的任何行都大。然而,具体的数值x,并 y依赖于并行执行语句生成自动递增值的数量。

    最后,考虑当最近生成的序列号为100时发布的以下语句:

    MySQL的> INSERT INTO t1 (c1,c2) VALUES (1,'a'), (NULL,'b'), (101,'c'), (NULL,'d');
    

    使用任何 innodb_autoinc_lock_mode 设置,此语句会生成重复键错误23000(Can't write; duplicate key in table),因为101分配给该行,(NULL, 'b')并且该行的 插入 (101, 'c')失败。

  • AUTO_INCREMENT在一系列INSERT语句 修改列值

    在所有锁定模式(0,1和2)中,修改语句AUTO_INCREMENT序列中间列值 INSERT可能会导致重复输入错误。例如,如果执行将 列值UPDATE更改为AUTO_INCREMENT大于当前最大自动增量值的INSERT 操作,则未指定未使用的自动增量值的后续操作可能会遇到重复输入 错误。以下示例演示了此行为。

    mysql> CREATE TABLE t1 (
        - > c1 INT NOT NULL AUTO_INCREMENT,
        - > PRIMARY KEY (c1)
        - >  ) ENGINE = InnoDB;
    
    MySQL的> INSERT INTO t1 VALUES(0), (0), (3);
    
    MySQL的> SELECT c1 FROM t1;
    + ---- +
    | c1 |
    + ---- +
    | 1 |
    | 2 |
    | 3 |
    + ---- +
    
    MySQL的> UPDATE t1 SET c1 = 4 WHERE c1 = 1;
    
    MySQL的> SELECT c1 FROM t1;
    + ---- +
    | c1 |
    + ---- +
    | 2 |
    | 3 |
    | 4 |
    + ---- +
    
    MySQL的> INSERT INTO t1 VALUES(0);
    错误1062(23000):键'PRIMARY'的重复条目'4'
    
InnoDB AUTO_INCREMENT计数器初始化

本节介绍如何InnoDB 初始化AUTO_INCREMENT计数器。

如果AUTO_INCREMENTInnoDB指定,则InnoDB数据字典中的表句柄 包含一个称为自动增量计数器的专用计数器,该计数器用于为该列分配新值。该计数器仅存储在主存储器中,而不是存储在磁盘上。

要在服务器重新启动后初始化自动增量计数器InnoDB,请将第一次插入时的以下语句的等效语句执行到包含AUTO_INCREMENT的表中

SELECT MAX(ai_col)FROM table_nameFOR UPDATE;

InnoDB递增由语句检索到的值并将其分配给表中的列和自动递增计数器。默认情况下,该值将增加1.此默认值可由auto_increment_increment 配置设置覆盖

如果表格为空,则InnoDB使用该值1该默认设置可以被auto_increment_offset 配置设置覆盖

如果SHOW TABLE STATUS 语句在自动递增计数器初始化之前检查该表,则InnoDB初始化但不增加该值。该值被存储以供稍后插入使用。此初始化在表上使用正常的独占锁定读取,并且锁持续到事务结束。InnoDB遵循相同的过程来初始化新创建的表的自动增量计数器。

在自动递增计数器初始化之后,如果您没有明确指定AUTO_INCREMENT的值 ,则 InnoDB递增计数器并将新值赋给该列。如果插入明确指定列值的行,并且该值大于当前计数器值,则将计数器设置为指定的列值。

InnoDB只要服务器运行,就会使用内存自动增量计数器。当服务器停止并重新启动时,如前所述InnoDB重新初始化第一个表的每个表的计数器 INSERT

服务器重新启动也会取消语句中的表选项 的效果 ,您可以使用它们来设置初始计数器值或更改当前计数器值。 AUTO_INCREMENT = NCREATE TABLEALTER TABLEInnoDB

14.8.1.6 InnoDB和FOREIGN KEY约束

该如何InnoDB存储引擎处理下,本节中的下列主题介绍外键约束:

有关外键使用信息和示例,请参见 第13.1.18.6节“使用外键约束”

外键定义

InnoDB表的 外键定义受以下条件限制:

  • InnoDB允许外键引用任何索引列或一组列。但是,在被引用的表中,必须有一个索引,其中被引用的列按照相同顺序列为 第一列。

  • InnoDB目前不支持具有用户定义分区的表的外键。这意味着没有用户分区的 InnoDB表可能包含外键引用或外键引用的列。

  • InnoDB允许外键约束引用非唯一键。这是InnoDB对标准SQL 扩展。

引用行为

InnoDB表的 外键引用操作 受以下条件限制:

  • 虽然SET DEFAULT被MySQL服务器允许,但被拒绝为无效 InnoDBCREATE TABLEALTER TABLE利用这一条款语句不得用于InnoDB表。

  • 如果父表中有多个具有相同引用键值的InnoDB 行,则在外键中执行操作就好像其他具有相同键值的父行不存在一样。例如,如果您定义了一个RESTRICT类型约束,并且存在具有多个父行的子行,InnoDB则不允许删除这些父行中的任何行。

  • InnoDB 基于对应于外键约束的索引中的记录,通过深度优先算法执行级联操作。

  • 如果ON UPDATE CASCADE或者ON UPDATE SET NULL递归更新它在级联期间先前更新过的 同一个表,它的行为就像 RESTRICT这意味着你不能使用自引用ON UPDATE CASCADEON UPDATE SET NULL操作。这是为了防止级联更新导致的无限循环。自引用的ON DELETE SET NULL,在另一方面,是可能的,因为是自引用ON DELETE CASCADE级联操作的嵌套深度不得超过15层。

  • 一般来说,就像MySQL一样,在一个SQL语句中,可以逐行插入,删除或更新许多行,InnoDB 检查UNIQUEFOREIGN KEY约束。执行外键检查时,InnoDB在必须查看的子记录或父记录上设置共享的行级锁。InnoDB立即检查外键约束; 该检查不会延迟到事务提交。根据SQL标准,默认行为应该是延迟检查。也就是说,只有在处理完整个SQL语句后才能检查约束直到 InnoDB 实现延迟约束检查,有些事情是不可能的,比如删除一个使用外键引用自己的记录。

生成列和虚拟索引的外键约束
  • 在一个外键约束 存储生成列无法使用ON UPDATE CASCADEON DELETE SET NULLON UPDATE SET NULLON DELETE SET DEFAULT,或ON UPDATE SET DEFAULT

  • 外键约束不能引用 虚拟生成的列

  • 在5.7.16之前,外键约束不能引用在虚拟生成列上定义的辅助索引。

  • 在MySQL 5.7.13及更早版本中,InnoDB 不允许在索引虚拟生成列基本列上使用级联参照操作定义外键约束 MySQL 5.7.14中解除了这个限制。

  • 在MySQL 5.7.13及更早版本中,InnoDB 不允许在显式包含在虚拟索引中的非虚拟外键列上定义级联参照操作MySQL 5.7.14中解除了这个限制。

外键使用和错误信息

您可以从查询INFORMATION_SCHEMA.KEY_COLUMN_USAGE 表中获得关于外键及其用法的一般信息 ,更多关于InnoDB更具体的信息 可以在 INNODB_SYS_FOREIGNINNODB_SYS_FOREIGN_COLS表中,也可以在INFORMATION_SCHEMA数据库中找到。

除了SHOW ERRORS涉及InnoDB的外键错误 (通常是MySQL服务器中的错误150),您可以InnoDB通过检查输出来获得最近一次外键错误 的详细解释SHOW ENGINE INNODB STATUS

14.8.1.7 InnoDB表的限制

InnoDB本部分的下列主题介绍表格限制

警告

不要转换在MySQL系统表 mysql从数据库 MyISAMInnoDB表。这是一个不受支持的操作。如果这样做,MySQL将不会重新启动,直到您从备份中还原旧系统表或通过重新初始化数据目录重新生成它们(请参见第2.10.1节“初始化数据目录”)。

警告

在使用NFS之前InnoDB,请查看使用NFS与MySQL中概述的潜在问题

最大值和最小值
  • 一个表最多可以包含1017列(在MySQL 5.6.9中从前面的限制1000提高)。虚拟生成的列包含在此限制中。

  • 一个表最多可以包含64个 二级索引

  • 如果innodb_large_prefix启用(默认),则对于InnoDB使用的表格 DYNAMICCOMPRESSED 行格式,索引键前缀限制为3072字节如果 innodb_large_prefix禁用,则任何行格式的表的索引键前缀限制为767字节。

    innodb_large_prefix 已弃用,将在未来版本中删除。 innodb_large_prefix在MySQL 5.5中引入,以禁用大型索引键前缀,以便与InnoDB不支持大型索引键前缀的早期版本兼容

    对于InnoDB使用REDUNDANTCOMPACT 行格式的表, 索引键前缀长度限制为767字节 例如,您可能会 在a 上使用列前缀索引超过255个字符 来达到此限制 ,并假设为aTEXTVARCHARutf8mb3字符集和每个字符的最大长度为3个字节

    尝试使用超过限制的索引键前缀长度将返回错误。为避免复制配置中出现此类错误,请避免启用 innodb_large_prefix在主服务器上启用它,如果它也不能在从服务器上启用。

    适用于索引键前缀的限制也适用于全列索引键。

  • 如果通过在创建MySQL实例时指定选项InnoDB 页面大小减小到8KB或4KB innodb_page_size,则根据16KB页面大小的3072字节的限制,索引键的最大长度将按比例降低。也就是说,当页面大小为8KB时,最大索引关键字长度为1536字节,当页面大小为4KB时,最大索引关键字长度为768字节。

  • 多列索引最多允许16列。超出限制会返回错误。

    错误1070(42000):指定的关键部件过多; 最多允许16个零件
    
  • 最大行长度,除了可变长度列(VARBINARYVARCHARBLOBTEXT),是比对于4KB,8KB,16KB,32KB和页大小的页的一半稍少。例如,默认innodb_page_size16KB 的最大行长度 大约为8000字节。对于InnoDB64KB 页面大小,最大行长度大约为16000字节。 LONGBLOB并且 LONGTEXT 列的长度必须小于4GB,并且行的总长度包括BLOBTEXT列)必须小于4GB。

    如果一行的长度小于半页,则所有行都存储在本地页面中。如果它超过半页,则可以选择可变长度的列用于外部页外存储,直到该行适合半页内为止,如第14.12.2节“文件空间管理”中所述

  • 虽然 InnoDB内部支持大于65,535字节的行大小,但MySQL本身对所有列的总大小施加了65,535的行大小限制:

    mysql> CREATE TABLE t (a VARCHAR(8000), b VARCHAR(10000),
        - > c VARCHAR(10000), d VARCHAR(10000), e VARCHAR(10000),
        - >f VARCHAR(10000), g VARCHAR(10000)) ENGINE=InnoDB;
    错误1118(42000):行大小太大。最大的行大小
    使用表类型,不计算BLOB,是65535.你必须改变一些
    列转换为TEXT或BLOB
    

    参见第C.10.4节“表列数量和行数限制”

  • 在一些较旧的操作系统上,文件必须小于2GB。这不是InnoDB 它本身的限制,但是如果你需要一个大的表空间,使用几个较小的数据文件而不是一个大的数据文件来配置它。

  • InnoDB日志文件 的组合大小可以达到512GB。

  • 最小的表空间大小略大于10MB。最大的表空间大小取决于 InnoDB页面大小。

    表14.6 InnoDB最大表空间大小

    InnoDB页面大小 最大表空间大小
    4KB 16TB
    8KB 32TB
    16KB 64TB
    32KB 128TB
    64KB 256TB

    最大表空间大小也是表的最大大小。

  • 默认页面大小InnoDB为16KB。您可以通过innodb_page_size在创建MySQL实例时配置选项来增加或减少页面大小

    ROW_FORMAT=COMPRESSED梭子鱼的文件格式假定页面大小最多为16KB,并使用14位指针。

    支持32KB和64KB的页面大小,但 ROW_FORMAT=COMPRESSED不支持大于16KB的页面大小。对于32KB和64KB页面大小,最大记录大小为16KB。因为 innodb_page_size=32k,范围的大小是2MB。因为 innodb_page_size=64k,范围大小是4MB。

    使用特定InnoDB页面大小的MySQL实例 不能使用来自使用不同页面大小的实例的数据文件或日志文件。

InnoDB表的限制
  • ANALYZE TABLE通过对每个索引树执行随机潜伏并相应地更新索引基数估计来确定索引基数(如 输出Cardinality栏中所示 SHOW INDEX因为这些只是估计,重复运行可能会产生不同的数字。这使得快速 ANALYZE TABLEANALYZE TABLEInnoDB表格但不是100%准确,因为它没有考虑所有行。

    您可以进行 统计 的收集ANALYZE TABLE 更精确,通过打开更稳定的 innodb_stats_persistent 配置选项,在解释 第14.6.12.1“配置持续优化程序统计参数”启用该设置后,重要的是ANALYZE TABLE在对索引列数据进行重大更改之后运行 ,因为不会定期重新计算统计信息(例如重新启动服务器之后)。

    如果启用持续统计设置,则可以通过修改innodb_stats_persistent_sample_pages 系统变量来更改随机潜水次数 如果持久统计设置被禁用,请修改 innodb_stats_transient_sample_pages 系统变量。

    MySQL在连接优化中使用索引基数估计。如果连接没有以正确的方式进行优化,请尝试使用ANALYZE TABLE在少数情况下,您的查询ANALYZE TABLE不会产生足够好的值,您可以使用FORCE INDEX查询来强制使用特定索引,或设置 max_seeks_for_key系统变量以确保MySQL优先于表扫描查找索引。参见第B.5.5节“与优化器相关的问题”

  • 如果语句或事务在一个表上运行,并且ANALYZE TABLE在同一个表 上运行,然后执行第二个 ANALYZE TABLE操作,则第二个ANALYZE TABLE 操作将被阻止,直到语句或事务完成。出现此现象的原因 ANALYZE TABLEANALYZE TABLE完成运行时将当前加载的表定义标记为过时 新的陈述或交易(包括第二个ANALYZE TABLE 语句)必须将新的表定义加载到表缓存中,直到当前正在运行的语句或事务完成并清除旧的表定义时才会发生这种情况。加载多个并发表定义不受支持。

  • SHOW TABLE STATUSInnoDB 除了表中保留的物理尺寸以外,不提供关于表的准确统计信息行数只是SQL优化中使用的粗略估计。

  • InnoDB不保留表中行的内部计数,因为并发事务可能同时 看到不同数量的行。因此,SELECT COUNT(*) 语句只计算当前事务可见的行。

    在MySQL 5.7.18之前,通过扫描聚集索引来InnoDB处理 SELECT COUNT(*)语句。从MySQL 5.7.18开始, 通过遍历较小的二级索引(如果存在)来InnoDB处理SELECT COUNT(*)语句。

    SELECT COUNT(*)如果索引记录不完​​全在缓冲池中, 处理语句需要一些时间。为了加快计数,您可以创建一个计数器表并让应用程序根据插入操作对其进行更新并删除它。但是,在数千个并发事务正在启动对同一个计数器表的更新的情况下,此方法可能无法很好地扩展。如果大致的行数足够, SHOW TABLE STATUS可以使用。

    InnoDB 以相同的方式处理SELECT COUNT(*)SELECT COUNT(1)操作。没有性能差异。

  • 在Windows上,InnoDB始终以小写形式存储数据库和表名。要将数据库以二进制格式从Unix移动到Windows或从Windows移动到Unix,请使用小写名称创建所有数据库和表。

  • AUTO_INCREMENTai_col必须被定义为一个指数,使得它能够进行一个索引的等效的部分上的表查找以获得最大列值。通常,这是通过将列设置为某个表索引的第一列来实现的。 SELECT MAX(ai_col)

  • InnoDB在与AUTO_INCREMENT相关联的索引的末尾设置排他锁, 同时初始化AUTO_INCREMENT表中先前指定的 列。

    随着 innodb_autoinc_lock_mode=0InnoDB使用一个特殊的 AUTO-INC地方在访问自动增长计数器获得锁并保持至当前的SQL语句的结束表锁定模式。AUTO-INC锁定表格锁定时,其他客户端无法插入表格 对于发生相同的行为批量插入innodb_autoinc_lock_mode=1表级AUTO-INC锁不用于 innodb_autoinc_lock_mode=2有关更多信息,请参见 第14.8.1.5节“InnoDB中的AUTO_INCREMENT处理”

  • 当您重新启动MySQL服务器时, InnoDB可以重新使用为AUTO_INCREMENT生成但从未存储的旧值(即在回滚的旧事务期间生成的值)。

  • 当一个AUTO_INCREMENT整数列用完值时,后续INSERT 操作将返回一个重复键错误。这是一般的MySQL行为。

  • DELETE FROM tbl_name 不会重新生成表格,而是会逐个删除所有行。

  • 级联外键操作不会激活触发器。

  • 不能创建与内部的名称匹配的列名的表InnoDB列(其中包括DB_ROW_IDDB_TRX_IDDB_ROLL_PTR,和 DB_MIX_ID)。此限制适用于在任何字母大小写中使用名称。

    MySQL的> CREATE TABLE t1 (c1 INT, db_row_id INT) ENGINE=INNODB;
    错误1166(42000):错误的列名'db_row_id'
    
锁定和交易
  • LOCK TABLESinnodb_table_locks=1(默认情况下)在每个表上获取两个锁 除了MySQL层的InnoDB表锁之外,它还获得表锁。4.1.2之前版本的MySQL没有获取 InnoDB表锁; 旧的行为可以通过设置来选择 innodb_table_locks=0如果没有 InnoDB获取表锁,LOCK TABLES即使某些表的记录被其他事务锁定也会完成。

    在MySQL 5.7中, innodb_table_locks=0对显式锁定的表没有任何影响 LOCK TABLES ... WRITE它对LOCK TABLES ... WRITE隐式(例如通过触发器)或通过隐式 读取或写入的表有效 LOCK TABLES ... READ

  • InnoDB事务持有的 所有锁都在事务提交或中止时释放。因此,它并没有多大意义,调用 LOCK TABLESInnoDB表中 autocommit=1模式,因为所获得的InnoDB表锁将被立即释放。

  • 您不能在事务中间锁定其他表,因为LOCK TABLES它执行隐式 COMMITUNLOCK TABLES

  • 数据修改事务的限制是产生撤消记录的96 * 1023个并发事务。将128个回滚段中的32个分配给用于修改临时表和相关对象的事务的非重做日志。这可以将并发数据修改事务的最大数量从128K减少到96K。96K限制假定事务不修改临时表。如果所有数据修改事务也修改临时表,则限制为32K个并发事务。

14.8.2 InnoDB索引

本节涵盖与InnoDB 索引相关的主题

14.8.2.1聚类索引和二级索引

每个InnoDB表都有一个称为聚集索引的特殊索引, 其中存储行的数据。通常,聚集索引与主键是同义的 为了从查询,插入和其他数据库操作中获得最佳性能,您必须了解如何InnoDB 使用聚簇索引来优化每个表的最常见查找和DML操作。

  • 当你PRIMARY KEY在你的表上定义一个时,InnoDB使用它作为聚集索引。为您创建的每个表定义一个主键。如果没有逻辑唯一且非空的列或一组列,请添加一个新的 自动增量 列,其值将自动填入。

  • 如果你没有PRIMARY KEY为你的表定义一个,MySQL将找到UNIQUE所有关键列的第一个 索引,NOT NULL并将 InnoDB它用作聚集索引。

  • 如果该表没有PRIMARY KEY具有合适的UNIQUE索引,则在 InnoDB内部生成一个隐藏的聚集索引GEN_CLUST_INDEX,该索引在包含行ID值的合成列上命名这些行按照InnoDB分配给此表中的行的ID进行排序行ID是一个6字节的字段,随着新行的插入而单调递增。因此,由行ID排序的行在物理上处于插入顺序。

聚集索引如何加快查询速度

通过聚集索引访问行很快,因为索引搜索直接导向包含所有行数据的页面。如果表很大,与使用与索引记录不同页面存储行数据的存储组织相比,聚簇索引体系结构通常会节省磁盘I / O操作。

二级指标如何与聚集指数相关联

除聚集索引以外的所有索引都称为 二级索引在中InnoDB,辅助索引中的每条记录都包含该行的主键列以及为辅助索引指定的列。 InnoDB使用此主键值搜索聚集索引中的行。

如果主键很长,二级索引使用更多空间,所以有一个短主键是有利的。

有关利用InnoDB 集群索引和二级索引的指导原则,请参见 第8.3节“优化和索引”

14.8.2.2 InnoDB索引的物理结构

除空间索引外,InnoDB 索引是B树数据结构。空间索引使用 R树,这是用于索引多维数据的专用数据结构。索引记录存储在B树或R树数据结构的叶页中。索引页面的默认大小是16KB。

将新记录插入到InnoDB 聚集索引时,会 InnoDB尝试将页面的1/16空闲以供将来插入和更新索引记录。如果索引记录以连续顺序(升序或降序)插入,则生成的索引页大约为15/16。如果记录以随机顺序插入,则页面从1/2到15/16满。

InnoDB在创建或重建B-tree索引时执行批量加载。这种索引创建方法被称为排序索引构建。innodb_fill_factor 配置选项定义的空间作为排序指标构建过程中填充,为今后指数增长预留的剩余空间每个B树页的百分比。空间索引不支持排序索引构建。有关更多信息,请参见第14.8.2.3节“分类索引构建”一个 innodb_fill_factor100设置叶免费为未来指数增长的聚簇索引页的空间的1/16。

如果InnoDB索引页面的填充因子降到低于MERGE_THRESHOLD默认值(如果未指定时为50%),则InnoDB尝试缩小索引树以释放页面。MERGE_THRESHOLD设置适用于B树和R树索引。有关更多信息,请参见 第14.6.13节“为索引页配置合并阈值”

您可以通过在初始化MySQL实例之前设置配置选项来为MySQL实例中的所有表空间 定义页面大小一旦定义了实例的页面大小,如果不重新初始化实例,则无法对其进行更改。支持的尺寸是64KB,32KB,16KB(默认),8KB,和4KB,对应于该选项值 ,和 InnoDBinnodb_page_size64k32k16k8k4k

在MySQL 5.7中增加了对32KB和64KB页面大小的支持。有关更多信息,请参阅 innodb_page_size文档。

使用特定InnoDB 页面大小的MySQL实例不能使用来自使用不同页面大小的实例的数据文件或日志文件。

14.8.2.3排序索引构建

InnoDB执行批量加载而不是在创建或重建索引时插入一个索引记录。这种索引创建方法也被称为排序索引构建。空间索引不支持排序索引构建。

索引构建有三个阶段。在第一阶段, 扫描聚集索引,并生成索引条目并将其添加到排序缓冲区。排序缓冲区变满时,条目将被排序并写出到临时中间文件。这个过程也被称为运行在第二阶段,将一个或多个运行写入临时中间文件,对文件中的所有条目执行合并排序。在第三阶段和最后阶段,将排序的条目插入 B树中

在引入排序索引构建之前,使用插入API一次将索引条目插入B树一条记录。此方法涉及打开B树 游标以查找插入位置,然后使用乐观插入将条目插入B树页面 如果由于页面已满而导致插入失败, 将执行悲观插入操作,这将涉及打开B树光标并根据需要拆分和合并B树节点以查找条目的空间。这种自上而下的弊端在于 构建索引的方法是搜索插入位置和B树节点的不断拆分和合并的成本。

排序索引构建使用自下而上建立索引的方法。通过这种方法,B树的所有级别都会引用最右边的页面页面。在必要的B树深度处的最右边的页面页被分配并且根据它们的排序顺序插入条目。一旦叶子页面已满,节点指针会附加到父页面上,并为下一个插入页面分配一个兄弟叶页面。该过程继续,直到插入所有条目,这可能导致插入到根级别。当分配兄弟页面时,将释放对先前固定的页面页面的引用,并且新分配的页面页面将成为最右侧的页面页面和新的默认插入位置。

为未来指数增长预留B树页面空间

要为未来的索引增长留出空间,可以使用 innodb_fill_factor 配置选项来保留B树页面空间的百分比。例如,innodb_fill_factor在排序索引构建期间,设置 为80保留B树页面中20%的空间。该设置适用于B树叶和非叶页。它不适用于用于TEXTBLOB输入的外部页面 保留的空间量可能与配置不完全相同,因为该 innodb_fill_factor值被解释为提示而非硬限制。

分类索引构建和全文索引支持

全文索引 支持排序索引构建 以前,SQL被用来将条目插入到全文索引中。

排序索引构建和压缩表

用于压缩表格,先前的索引创建方法将条目附加到压缩页面和未压缩页面。当修改日志(代表压缩页面上的可用空间)变满时,压缩的页面将被重新压缩。如果由于空间不足而导致压缩失败,页面将被拆分。使用排序索引构建时,条目仅附加到未压缩页面。当一个未压缩的页面变满时,它被压缩。自适应填充用于确保在大多数情况下压缩能够成功,但如果压缩失败,则会拆分页面并再次尝试压缩。这个过程一直持续到压缩成功。有关B-Tree页面压缩的更多信息,请参阅 第14.9.1.5节“InnoDB表的压缩是如何工作的”

排序索引构建和重做日志记录

重排日志在排序索引构建过程中被禁用。相反,有一个 检查点可确保索引构建能够承受崩溃或故障。检查点强制将所有脏页写入磁盘。在排序的索引构建期间,页面清理器 线程会定期发送信号以刷新 脏页面,以确保可以快速处理检查点操作。通常,当干净页面数量低于设定阈值时,页面清理器线程会刷新脏页面。对于有序的索引构建,会立即刷新脏页以减少检查点开销并且平行化I / O和CPU活动。

排序索引构建和优化器统计

排序索引构建可能会导致 优化器统计信息与先前创建索引方法所生成的统计信息不同。预计不会影响工作负载性能的统计差异是由于用于填充索引的算法不同所致。

14.8.2.4 InnoDB FULLTEXT索引

FULLTEXT索引是在基于文本的列(CHARVARCHARTEXT列)上创建的以帮助加快对包含在这些列中的数据的查询和DML操作,省略任何定义为停用词的单词。

FULLTEXT指数被定义为一个的一部分 CREATE TABLE说明或使用添加到现有的表ALTER TABLECREATE INDEX

全文搜索使用MATCH() ... AGAINST语法来执行有关使用信息,请参见 第12.9节“全文搜索功能”

InnoDB FULLTEXT 索引在本节中的以下主题下进行介绍:

InnoDB全文索引设计

InnoDB FULLTEXT指数具有倒排指数设计。倒排索引存储单词列表,并为每个单词列出单词出现的文档列表。为支持邻近搜索,每个单词的位置信息也以字节偏移量的形式存储。

InnoDB全文索引表

创建InnoDB FULLTEXT索引时,会创建一组索引表,如下例所示:

MySQL的> CREATE TABLE opening_lines (
       id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
       opening_line TEXT(500),
       author VARCHAR(200),
       title VARCHAR(200),
       FULLTEXT idx (opening_line)
       ) ENGINE=InnoDB;

MySQL的> SELECT table_id, name, space from INFORMATION_SCHEMA.INNODB_SYS_TABLES
       WHERE name LIKE 'test/%';
+ ---------- + -------------------------------------- -------------- + ------- +
| table_id | 名称| 空间|
+ ---------- + -------------------------------------- -------------- + ------- +
| 333 | 测试/ FTS_0000000000000147_00000000000001c9_INDEX_1 | 289 |
| 334 | 测试/ FTS_0000000000000147_00000000000001c9_INDEX_2 | 290 |
| 335 | 测试/ FTS_0000000000000147_00000000000001c9_INDEX_3 | 291 |
| 336 | 测试/ FTS_0000000000000147_00000000000001c9_INDEX_4 | 292 |
| 337 | 测试/ FTS_0000000000000147_00000000000001c9_INDEX_5 | 293 |
| 338 | 测试/ FTS_0000000000000147_00000000000001c9_INDEX_6 | 294 |
| 330 | 测试/ FTS_0000000000000147_BEING_DELETED | 286 |
| 331 | 测试/ FTS_0000000000000147_BEING_DELETED_CACHE | 287 |
| 332 | 测试/ FTS_0000000000000147_CONFIG | 288 |
| 328 | 测试/ FTS_0000000000000147_DELETED | 284 |
| 329 | 测试/ FTS_0000000000000147_DELETED_CACHE | 285 |
| 327 | test / opening_lines | 283 |
+ ---------- + -------------------------------------- -------------- + ------- + 

前六个表格表示倒排索引,并被称为辅助索引表。当输入文档被标记时,单个词(也称为 标记)与位置信息和相关联的文档ID(DOC_ID一起被插入到索引表中基于字的第一个字符的字符集分类权重,字被完全排序并在六个索引表中分区。

倒排索引被分成六个辅助索引表以支持并行索引创建。默认情况下,两个线程将标记,排序并将单词和关联数据插入到索引表中。线程数可以使用该innodb_ft_sort_pll_degree 选项进行配置 考虑FULLTEXT在大型表上创建索引时增加线程数

辅助索引表名以前缀FTS_和后缀 为前缀 INDEX_*每个索引表都通过索引表名称中与table_id索引表匹配的十六进制值与索引表相关联例如,table_id所述的 test/opening_lines表是 327,为此,十六进制值是0x147。如上例所示,147十六进制值出现在与该test/opening_lines关联的索引表的名称中

表示的十六进制值index_id的的FULLTEXT索引也出现在辅助索引表名。例如,在辅助表名称中 test/FTS_0000000000000147_00000000000001c9_INDEX_1,十六进制值1c9的十进制值为457. 可以通过查询 表(457)来确定opening_lines 表(idx上定义的索引INFORMATION_SCHEMA.INNODB_SYS_INDEXES

MySQL的> SELECT index_id, name, table_id, space from INFORMATION_SCHEMA.INNODB_SYS_INDEXES
       WHERE index_id=457;
+ ---------- + ------ + ---------- + ------- +
| index_id | 名称| table_id | 空间|
+ ---------- + ------ + ---------- + ------- +
| 457 | idx | 327 | 283 |
+ ---------- + ------ + ---------- + ------- +

如果主表是在每个表文件表 空间中创建的,则索引表将存储在其自己 的表空间中。

上例中显示的其他索引表称为公共索引表,用于删除处理和存储FULLTEXT索引的内部状态 与为每个全文索引创建的倒排索引表不同,这组表对于在特定表上创建的所有全文索引都是通用的。

即使全文索引被删除,通用辅助表也会被保留。删除全文索引时, FTS_DOC_ID保留为索引创建的FTS_DOC_ID,因为删除 列需要重建表。管理FTS_DOC_ID色谱柱需要共同的腋窝表

  • FTS_*_DELETEDFTS_*_DELETED_CACHE

    包含已删除但其数据尚未从全文索引中删除的文档的文档ID(DOC_ID)。FTS_*_DELETED_CACHE是该FTS_*_DELETED的内存中版本

  • FTS_*_BEING_DELETEDFTS_*_BEING_DELETED_CACHE

    包含已删除文档的文档ID(DOC_ID),其数据当前正在从全文索引中删除。FTS_*_BEING_DELETED_CACHE表是表的内存中版本 FTS_*_BEING_DELETED

  • FTS_*_CONFIG

    存储有关FULLTEXT索引内部状态的信息 最重要的是,它存储了FTS_SYNCED_DOC_ID标识已被分析并刷新到磁盘的文档。在崩溃恢复的情况下, FTS_SYNCED_DOC_ID值用于标识尚未刷新到磁盘的文档,以便可以重新解析文档并将其添加回 FULLTEXT索引缓存。要查看此表中的数据,请查询该 INFORMATION_SCHEMA.INNODB_FT_CONFIG 表。

InnoDB全文索引缓存

插入文档时,会将其标记,并将单个词和关联的数据插入到 FULLTEXT索引中。即使对于小文档,这个过程可能导致大量的小插入到辅助索引表中,使得这些表的并发访问成为争用点。为避免此问题,请 InnoDB使用FULLTEXT 索引缓存临时缓存最近插入的行的索引表插入。这个内存中的缓存结构持有插入,直到缓存满了,然后将它们批量刷新到磁盘(到辅助索引表)。您可以查询该 INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE 表以查看最近插入的行的标记化数据。

缓存和批量刷新行为避免了对辅助索引表的频繁更新,这可能会导致在繁忙的插入和更新时间期间出现并发访问问题。批处理技术还避免了同一单词的多次插入,并最大限度地减少了重复条目。不是单独刷新每个单词,而是将同一单词的插入作为单个条目合并并刷新到磁盘,从而提高插入效率,同时保持辅助索引表尽可能小。

innodb_ft_cache_size 变量用于配置全文索引缓存大小(基于每个表),这会影响刷新全文索引缓存的频率。您还可以使用该innodb_ft_total_cache_size 选项为给定实例中的所有表定义全局全文索引缓存大小限制

全文索引缓存存储与辅助索引表相同的信息。但是,全文索引缓存仅缓存最近插入的行的标记化数据。查询时,已经刷新到磁盘(到全文辅助表)的数据不会被带回到全文索引缓存中。辅助索引表中的数据直接被查询,并且辅助索引表中的结果与返回前的全文索引缓存的结果合并。

InnoDB全文索引文档ID和FTS_DOC_ID列

InnoDB使用称为文档ID(DOC_ID的唯一文档标识符将全文索引中的单词映射到出现该单词的文档记录。该映射需要FTS_DOC_ID索引表上的列。如果FTS_DOC_ID未定义 列,则在创建全文索引时InnoDB自动添加隐藏 FTS_DOC_ID列。以下示例演示了此行为。

下表定义不包括一 FTS_DOC_ID列:

MySQL的> CREATE TABLE opening_lines (
       id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
       opening_line TEXT(500),
       author VARCHAR(200),
       title VARCHAR(200)
       ) ENGINE=InnoDB;   

当您使用CREATE FULLTEXT INDEX语法在表上创建全文索引时,将 返回一个警告,报告InnoDB重建表以添加该FTS_DOC_ID 列。

MySQL的> CREATE FULLTEXT INDEX idx ON opening_lines(opening_line);
查询OK,0行受影响,1个警告(0.19秒)
记录:0重复:0警告:1

MySQL的> SHOW WARNINGS;
+ --------- + ------ + -------------------------------- ------------------ +
| 级别| 代码| 留言|
+ --------- + ------ + -------------------------------- ------------------ +
| 警告| 124 | InnoDB重建表添加列FTS_DOC_ID |
+ --------- + ------ + -------------------------------- ------------------ +

使用ALTER TABLE将全文索引添加到没有FTS_DOC_ID的表时,会 返回相同的警告 如果您在CREATE TABLE 时间创建全文索引并且未指定FTS_DOC_ID 列,请InnoDB添加隐藏 FTS_DOC_ID列,而不发出警告。

FTS_DOC_IDCREATE TABLE时间上 定义比在已经加载数据的表上创建全文索引便宜。如果FTS_DOC_ID 在加载数据之前在表上定义列,则不必重建表及其索引以添加新列。如果您不关注CREATE FULLTEXT INDEX性能,请忽略该 FTS_DOC_IDInnoDB以为您创建它。 InnoDB创建一个隐藏的 FTS_DOC_ID列以及FTS_DOC_ID_INDEXFTS_DOC_ID唯一的索引(如果您想创建自己的FTS_DOC_ID列,则该列必须被定义为BIGINT UNSIGNED NOT NULL并命名FTS_DOC_ID (全部大写),如下例所示:

注意

FTS_DOC_ID列不需要定义为AUTO_INCREMENT列,但 AUTO_INCREMENT可以使加载数据更容易。

MySQL的> CREATE TABLE opening_lines (
       FTS_DOC_ID BIGINT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
       opening_line TEXT(500),
       author VARCHAR(200),
       title VARCHAR(200)
       ) ENGINE=InnoDB;    

如果您选择自己定义FTS_DOC_ID 列,则负责管理列以避免空值或重复值。 FTS_DOC_ID值不能被重用,这意味着FTS_DOC_ID值必须不断增加。

或者,您可以FTS_DOC_ID_INDEXFTS_DOC_ID创建所需的唯一 (全部大写)

MySQL的> CREATE UNIQUE INDEX FTS_DOC_ID_INDEX on opening_lines(FTS_DOC_ID);

如果你不创建FTS_DOC_ID_INDEXInnoDB自动创建它。

在MySQL 5.7.13之前,最大使用FTS_DOC_ID值和新 FTS_DOC_ID之间的允许差距为10000.在MySQL 5.7.13和更高版本中,允许的差距为65535。

为了避免重建表格,FTS_DOC_ID在删除全文索引时保留列。

InnoDB全文索引删除处理

删除具有全文索引列的记录可能会导致辅助索引表中的许多小的删除操作,从而使这些表的并发访问成为争用点。为避免此问题,每当从索引表中删除DOC_ID记录时,已删除文档的文档ID()都会记录在特殊FTS_*_DELETED表中,并且索引记录保留在全文索引中。在返回查询结果之前,FTS_*_DELETED 表用于过滤掉已删除的文档ID。这种设计的好处是删除速度快而且价格低廉。缺点是在删除记录后索引的大小不会立即减小。要删除已删除记录的全文索引条目,请OPTIMIZE TABLE在索引表上 运行innodb_optimize_fulltext_only=ON 以重建全文索引。有关更多信息,请参阅 优化InnoDB全文索引

InnoDB全文索引事务处理

InnoDB FULLTEXT由于缓存和批处理行为,索引具有特殊的事务处理特性。具体而言,FULLTEXT在事务提交时处理索引上的更新和插入,这意味着 FULLTEXT搜索只能看到已提交的数据。以下示例演示了此行为。FULLTEXT搜索只返回插入的行被提交之后的结果。

MySQL的> CREATE TABLE opening_lines (
       id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
       opening_line TEXT(500),
       author VARCHAR(200),
       title VARCHAR(200),
       FULLTEXT idx (opening_line)
       ) ENGINE=InnoDB;

MySQL的> BEGIN;

MySQL的> INSERT INTO opening_lines(opening_line,author,title) VALUES
       ('Call me Ishmael.','Herman Melville','Moby-Dick'),
       ('A screaming comes across the sky.','Thomas Pynchon','Gravity\'s Rainbow'),
       ('I am an invisible man.','Ralph Ellison','Invisible Man'),
       ('Where now? Who now? When now?','Samuel Beckett','The Unnamable'),
       ('It was love at first sight.','Joseph Heller','Catch-22'),
       ('All this happened, more or less.','Kurt Vonnegut','Slaughterhouse-Five'),
       ('Mrs. Dalloway said she would buy the flowers herself.','Virginia Woolf','Mrs. Dalloway'),
       ('It was a pleasure to burn.','Ray Bradbury','Fahrenheit 451');

MySQL的> SELECT COUNT(*) FROM opening_lines WHERE MATCH(opening_line) AGAINST('Ishmael');
+ ---------- +
| COUNT(*)|
+ ---------- +
| 0 |
+ ---------- +

MySQL的> COMMIT;

MySQL的> SELECT COUNT(*) FROM opening_lines WHERE MATCH(opening_line) AGAINST('Ishmael');
+ ---------- +
| COUNT(*)|
+ ---------- +
| 1 |
+ ---------- +
监控InnoDB全文索引

您可以InnoDB FULLTEXT通过查询以下INFORMATION_SCHEMA表格来监视和检查索引 的特殊文本处理方面

您还可以FULLTEXT通过查询INNODB_SYS_INDEXES查看索引和表格的 基本信息 INNODB_SYS_TABLES

有关更多信息,请参见 第14.15.4节“InnoDB INFORMATION_SCHEMA全文索引表”

14.9 InnoDB表和页面压缩

本节提供有关 InnoDB表压缩和 InnoDB页面压缩功能的信息。页面压缩功能被称为 透明页面压缩

使用压缩功能InnoDB,您可以创建表格,以压缩形式存储数据。压缩有助于提高原始性能和可扩展性。压缩意味着更少的数据在磁盘和内存之间传输,并且占用磁盘和内存中的更少空间。对于具有二级索引的表格,这些好处会被放大 ,因为索引数据也会被压缩。压缩对于SSD存储设备尤其重要,因为它们的容量往往低于 HDD设备。

14.9.1 InnoDB表压缩

本节介绍InnoDB表压缩,该表压缩由InnoDB 驻留在 file_per_table 表空间或常规表空间中的表支持表压缩通过使用or ROW_FORMAT=COMPRESSED属性 来启用 CREATE TABLEALTER TABLE

14.9.1.1表压缩概述

由于处理器和缓存内存的速度比磁盘存储设备的速度提高得多,因此许多工作负载都是 磁盘绑定的数据 压缩能够实现更小的数据库大小,减少I / O并提高吞吐量,同时以较少的CPU利用率提高成本。对于读密集型应用程序而言,压缩尤其有价值,因为系统具有足够的RAM以将频繁使用的数据保存在内存中。

InnoDB创建ROW_FORMAT=COMPRESSED可以在磁盘上使用比配置小的 页面大小innodb_page_size较小的页面需要较少的I / O读取和写入磁盘,这对SSD设备特别有用

压缩的页面大小通过CREATE TABLE参数指定 由于系统表空间不能存储压缩表,因此不同的页面大小要求将表放置在 每个表文件的文件表 空间或常规表空间中,而不是放在 系统表空间中。有关更多信息,请参见 第14.7.4节“InnoDB每个表文件的表空间”第14.7.9节“InnoDB常规表空间”ALTER TABLE KEY_BLOCK_SIZE

不管KEY_BLOCK_SIZE如何,压缩级别都是相同的 当您指定较小的值时KEY_BLOCK_SIZE,您可以获得越来越小页面的I / O优势。但是,如果您指定的值太小,则当数据值无法压缩到足以适应每个页面中的多行时,会有额外的开销来重新组织页面。KEY_BLOCK_SIZE根据每个索引的键列长度,对于表格的小小可以有一个严格限制指定值过小, CREATE TABLEALTER TABLE语句失败。

在缓冲池中,压缩数据保存在小页面中,页面大小基于该KEY_BLOCK_SIZE 值。为了提取或更新列值,MySQL还使用未压缩的数据在缓冲池中创建一个未压缩的页面。在缓冲池中,对未压缩页面的任何更新也会重新写回等效的压缩页面。您可能需要调整缓冲池的大小以适应压缩和未压缩页面的额外数据,尽管未压缩的页面在 需要空间时从缓冲池中逐出,然后在下次访问时再次解压缩。

14.9.1.2创建压缩表

压缩表可以在 每个表的文件表 空间或 一般的表空间中创建表压缩不适用于InnoDB 系统表空间系统表空间(空间0, .ibdata文件)可以包含用户创建的表,但它也包含内部系统数据,这些数据从不压缩。因此,压缩仅适用于存储在每个文件或一般表空间中的表(和索引)。

在每个文件表空间中创建一个压缩表

要在每个表的文件表空间中创建压缩表, innodb_file_per_table必须启用(MySQL 5.6.6中的默认innodb_file_format设置)并且 必须设置为Barracuda您可以使用 语句在MySQL配置文件(my.cnfmy.ini)中或动态地 设置这些参数SET

配置innodb_file_per_tableinnodb_file_format选项,在a 语句中指定 ROW_FORMAT=COMPRESSED子句或 KEY_BLOCK_SIZE子句或两者,以 在每个文件表的表空间中创建一个压缩表。 CREATE TABLEALTER TABLE

例如,您可以使用以下语句:

SET GLOBAL innodb_file_per_table = 1;
SET GLOBAL innodb_file_format =梭鱼;
创建表t1
 (c1 INT主键)
 ROW_FORMAT = COMPRESSED
 KEY_BLOCK_SIZE = 8;
在常规表空间中创建压缩表

要在常规表空间中创建压缩表, FILE_BLOCK_SIZE必须为创建表空间时指定的常规表空间定义。FILE_BLOCK_SIZE值必须是与值相关的有效压缩页面大小 innodb_page_size,并且由CREATE TABLEor 子句定义的压缩表的页面大小 必须等于 例如,如果 表的值必须为8.有关更多信息,请参见第14.7.9节“InnoDB常规表空间”ALTER TABLE KEY_BLOCK_SIZEFILE_BLOCK_SIZE/1024innodb_page_size=16384FILE_BLOCK_SIZE=8192KEY_BLOCK_SIZE

以下示例演示如何创建常规表空间并添加压缩表。该示例假设默认 innodb_page_size值为16K。FILE_BLOCK_SIZE8192要求压缩表有KEY_BLOCK_SIZE8个。

MySQL的> CREATE TABLESPACE `ts2` ADD DATAFILE 'ts2.ibd' FILE_BLOCK_SIZE = 8192 Engine=InnoDB;

MySQL的> CREATE TABLE t4 (c1 INT PRIMARY KEY) TABLESPACE ts2 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
笔记
  • 如果你指定ROW_FORMAT=COMPRESSED,你可以省略KEY_BLOCK_SIZE; KEY_BLOCK_SIZE设置默认为innodb_page_size值的一半

  • 如果您指定了有效的KEY_BLOCK_SIZE 值,则可以省略 ROW_FORMAT=COMPRESSED; 压缩自动启用。

  • 要确定最佳值, KEY_BLOCK_SIZE,通常可以为此子句创建具有不同值的同一表的多个副本,然后测量结果.ibd文件的大小,并查看每个副本对于 实际工作负载的执行情况 对于常规表空间,请记住,删除表不会减小常规表空间.ibd文件的大小 ,也不会将磁盘空间返回给操作系统。有关更多信息,请参见 第14.7.9节“InnoDB常规表空间”

  • KEY_BLOCK_SIZE值被视为提示; InnoDB如果需要,可以使用不同的尺寸 对于每个文件表的表空间,KEY_BLOCK_SIZE只能小于或等于该 innodb_page_size值。如果指定的值大于该 innodb_page_size值,则会忽略指定的值,发出警告,并将 KEY_BLOCK_SIZE其设置为该innodb_page_size值的一半 如果 innodb_strict_mode=ON指定一个无效KEY_BLOCK_SIZE值会返回一个错误。对于一般的表空间,有效值 KEY_BLOCK_SIZE取决于FILE_BLOCK_SIZE表空间设置。有关更多信息,请参阅 第14.7.9节“InnoDB常规表空间”

  • 32k和64k页面大小不支持压缩。有关更多信息,请参阅 innodb_page_size 文档。

  • InnoDB 数据页面 的默认未压缩大小为16KB。根据选项值的组合,MySQL为表空间数据文件(.ibd文件)使用1KB,2KB,4KB,8KB或16KB的页面大小实际的压缩算法不受该KEY_BLOCK_SIZE值的影响 ; 该值确定每个压缩块有多大,这反过来又影响可以将每行压缩到每个压缩页中的行数。

  • 在每个文件表的表空间中创建压缩表时,设置KEY_BLOCK_SIZE等于InnoDB 页面大小通常不会导致太多的压缩。例如, KEY_BLOCK_SIZE=16由于正常InnoDB页面大小为16KB ,因此通常不会导致太多压缩 此设置可能仍然是许多长条桌有用的 BLOBVARCHARTEXT列,因为这种价值观往往压缩得很好,因此可能需要较少的溢出页中描述 第14.9.1.5,“如何压缩适用于InnoDB表”对于一般的表空间,不允许KEY_BLOCK_SIZE等于InnoDB页面大小有关更多信息,请参见 第14.7.9节“InnoDB常规表空间”

  • 表(包括聚集索引)的所有索引 都使用与CREATE TABLEor ALTER TABLE语句中指定的相同页面大小进行压缩 表格属性(如 ROW_FORMAT和) KEY_BLOCK_SIZE不是表格CREATE INDEX语法的 一部分 InnoDB,如果指定它们(如果指定,它们将出现在SHOW CREATE TABLE语句的输出中将被忽略

  • 有关与性能相关的配置选项,请参见 第14.9.1.3节“调整InnoDB表的压缩”

压缩表的限制
  • 5.1之前的MySQL版本无法处理压缩表。

  • 压缩的表不能存储在 InnoDB系统表空间中。

  • 常规表空间可以包含多个表,但是压缩和未压缩的表不能共存于同一个通用表空间中。

  • 压缩适用于整个表及其所有关联索引,而不适用于单个行,尽管使用了子句名称ROW_FORMAT

14.9.1.3调整InnoDB表的压缩

InnoDB数据存储和压缩中 描述的内部优化通常会 确保系统在压缩数据下运行良好。但是,由于压缩效率取决于数据的性质,因此可以制定影响压缩表性能的决策:

  • 要压缩哪些表格。

  • 什么压缩页面大小使用。

  • 是否根据运行时性能特征调整缓冲池的大小,例如系统花费压缩和解压缩数据的时间量。工作负载是否更像 数据仓库 (主要是查询)或 OLTP系统(混合查询和DML)。

  • 如果系统在压缩表上执行DML操作,并且数据分布的方式会在运行时导致昂贵的 压缩失败,则可以调整其他高级配置选项。

使用本节中的准则来帮助进行这些架构和配置选择。当您准备好进行长期测试并将压缩表投入生产时,请参见 第14.9.1.4节“在运行时监控InnoDB表压缩”,了解验证这些选择在真实条件下的有效性的方法。

何时使用压缩

一般来说,压缩在包含合理数量的字符串列的表上工作得最好,并且数据读取的次数比写入的次数要多得多。因为没有可靠的方法来预测压缩是否有利于特定情况,所以请始终使用代表性配置上运行的特定工作负载和数据集进行测试 决定要压缩哪些表时请考虑以下因素。

数据特征和压缩

数据文件大小压缩效率的关键决定因素是数据本身的性质。回想一下,压缩的工作原理是通过识别数据块中的重复字节串。完全随机数据是最糟糕的情况。典型的数据通常具有重复的值,因此有效地压缩。字符串经常压缩得很好,在是否定义CHARVARCHARTEXTBLOB列。另一方面,主要包含二进制数据(整数或浮点数)或先前压缩的数据(例如JPEGPNG 图像)的表格通常可能无法很好地压缩,显着或根本不压缩。

您可以选择是否为每个InnoDB表打开压缩。表及其所有索引使用相同(压缩)的 页面大小主键 (聚集)索引可能比二级索引更有效地压缩,其中包含表中所有列的数据。对于存在长行的情况,使用压缩可能导致长列值被存储为 离页,如 第14.11.3节“动态和压缩行格式”中所述。这些溢出页面可能压缩得很好。鉴于这些考虑因素,对于许多应用程序,某些表比其他表压缩更有效,并且您可能会发现只有压缩表的子集才能使工作负载表现最佳。

要确定是否要压缩某个表,请进行实验。您可以粗略地估算一下,如何通过在未压缩表gzip.ibd文件的副本上使用实现LZ77压缩的实用程序(如WinZip)来压缩数据的效率您可以期望从MySQL压缩表压缩比从基于文件的压缩工具更少的压缩,因为MySQL根据页面大小压缩数据块,默认为16KB。除用户数据外,页面格式还包括一些未压缩的内部系统数据。基于文件的压缩实用程序可以检查更大的数据块,因此可能会在MySQL文件中找到的大文件中找到更多重复的字符串。

在特定表上测试压缩的另一种方法是将一些数据从未压缩的表中复制到每个文件表的表 空间中类似的压缩表(具有所有相同的索引), 并查看生成.ibd文件的大小 例如:

USE测试;
SET GLOBAL innodb_file_per_table = 1;
SET GLOBAL innodb_file_format =梭鱼;
SET GLOBAL autocommit = 0;

- 创建一个具有一百或两行的未压缩表。
CREATE TABLE big_table AS SELECT * FROM information_schema.columns;
INSERT INTO big_table SELECT * FROM big_table;
INSERT INTO big_table SELECT * FROM big_table;
INSERT INTO big_table SELECT * FROM big_table;
INSERT INTO big_table SELECT * FROM big_table;
INSERT INTO big_table SELECT * FROM big_table;
INSERT INTO big_table SELECT * FROM big_table;
INSERT INTO big_table SELECT * FROM big_table;
INSERT INTO big_table SELECT * FROM big_table;
INSERT INTO big_table SELECT * FROM big_table;
INSERT INTO big_table SELECT * FROM big_table;
承诺;
ALTER TABLE big_table ADD id int unsigned NOT NULL PRIMARY KEY auto_increment;

SHOW CREATE TABLE big_table \ G

从big_table中选择count(id);

- 检查未压缩表格需要多少空间。
\!ls -l data / test / big_table.ibd

CREATE TABLE key_block_size_4 LIKE big_table;
ALTER TABLE key_block_size_4 key_block_size = 4 row_format = compressed;

INSERT INTO key_block_size_4 SELECT * FROM big_table;
承诺;

- 检查压缩表需要多少空间
- 使用特定的压缩设置。
\!ls -l data / test / key_block_size_4.ibd

这个实验产生了下面的数字,这当然会根据你的表格结构和数据而有很大的不同:

-rw-rw ---- 1卷绕工作人员310378496 Jan 9 13:44 data / test / big_table.ibd
-rw-rw ---- 1卷绕工作人员83886080 Jan 9 15:10 data / test / key_block_size_4.ibd

要查看压缩对于您的特定工作负载是否有效

数据库压缩与应用程序压缩

决定是否压缩应用程序或表中的数据; 请勿对同一数据使用两种类型的压缩。当您在应用程序中压缩数据并将结果存储在压缩表中时,极其不可能节省额外的空间,而双重压缩只会浪费CPU周期。

在数据库中压缩

启用时,MySQL表压缩是自动的,适用于所有列和索引值。LIKE即使索引值被压缩,仍然可以使用运算符(例如,)对列进行测试,并且排序操作仍然可以使用索引。由于索引通常占数据库总大小的很大一部分,因此压缩可能会显着节省存储空间,I / O或处理器时间。压缩和解压缩操作发生在数据库服务器上,这可能是一个处理预期负载的功能强大的系统。

在应用程序中压缩

如果在应用程序中压缩数据(例如文本),然后将其插入数据库中,则可以通过压缩某些列而不是压缩某些列来节省数据压缩的开销。这种方法在客户端机器上使用CPU周期进行压缩和解压缩,而非数据库服务器,这可能适用于拥有多个客户端的分布式应用程序,或客户端计算机具有空闲CPU周期的情况。

混合方法

当然,可以将这些方法结合起来。对于某些应用程序,可能适合使用一些压缩表和一些未压缩的表。最好从外部压缩一些数据(并将其存储在未压缩的表中),并允许MySQL压缩(某些)应用程序中的其他表。与往常一样,前期设计和实际测试对于做出正确的决定是有价值的。

工作量特征和压缩

除了选择要压缩的表格(以及页面大小)之外,工作负载还是性能的另一个关键决定因素。如果应用程序由读取操作而非更新操作占据主导地位,那么在索引页空间不足以满足MySQL为压缩数据维护的每页修改日志之后,需要重新组织和重新压缩页面如果更新主要更改非索引列或包含BLOBs或大字符串的那些恰好存储为脱离页面 ”的列,则压缩的开销可能是可接受的。如果唯一的变化是表格INSERTs使用单调递增的主键,并且二级索引很少,因此很少需要重新组织和重新压缩索引页。由于MySQL能够删除标记,并删除压缩的页面行到位通过修改未压缩的数据,DELETE在表上的操作都比较高效。

对于某些环境,加载数据所需的时间与运行时检索一样重要。特别是在数据仓库环境中,许多表可能是只读的或只读的。在这种情况下,在增加加载时间方面支付压缩的价格可能会也可能不会被接受,除非节省更少的磁盘读取或存储成本是显着的。

基本上,当CPU时间可用于压缩和解压缩数据时,压缩效果最佳。因此,如果您的工作负载受I / O限制,而不是CPU限制,则可能会发现压缩可以提高整体性能。当您使用不同的压缩配置测试应用程序性能时,请在类似于生产系统计划配置的平台上进行测试。

配置特征和压缩

从磁盘 读写数据库 页面是系统性能最慢的一个方面。压缩尝试通过使用CPU时间来压缩和解压缩数据来减少I / O,并且当I / O与处理器周期相比是相对稀缺的资源时最为有效。

在具有快速多核CPU的多用户环境中运行时,情况尤其如此。当压缩表的页面在内存中时,MySQL通常在缓冲池中使用额外的内存(通常为16KB)来存储 页面的未压缩副本。自适应LRU算法试图平衡压缩和未压缩页面之间的内存使用情况,以考虑工作负载是以I / O绑定还是CPU绑定的方式运行。尽管如此,具有更多专用于缓冲池的内存的配置在使用压缩表时比使用高度受限内存的配置更好。

选择压缩页面大小

压缩页面大小的最佳设置取决于表及其索引所包含数据的类型和分布。压缩的页面大小应该始终大于最大记录大小,否则操作可能会失败,如 “B-Tree页面的压缩”中所述

将压缩的页面尺寸设置得太大会浪费一些空间,但页面不必经常压缩。如果压缩的页面大小设置得太小,则插入或更新可能需要耗费时间的重新压缩,并且 B树节点可能不得不更频繁地分割,导致更大的数据文件和更低效的索引。

通常,您将压缩的页面大小设置为8K或4K字节。鉴于InnoDB表的最大行大小约为8K,KEY_BLOCK_SIZE=8通常是安全的选择。

14.9.1.4运行时监控InnoDB表压缩

总体应用程序性能,CPU和I / O利用率以及磁盘文件的大小是有效压缩对您的应用程序的有效指标。本节基于第14.9.1.3节“调整InnoDB表的压缩”中的性能调整建议 ,并展示如何查找在初始测试期间可能不会出现的问题。

要深入了解压缩表的性能注意事项,可以使用例14.1“使用压缩信息模式表”中介绍信息模式监视压缩表的运行时压缩性能这些表格反映了内存的内部使用和整体使用的压缩率。

INNODB_CMP表报告有关使用中的每个压缩页面大小(KEY_BLOCK_SIZE)的压缩活动的信息这些表中的信息是系统范围的:它汇总了数据库中所有压缩表的压缩统计信息。您可以使用此数据来帮助您决定是否在没有其他压缩表正在访问时通过检查这些表来压缩表。它在服务器上的开销相对较低,因此您可能会定期在生产服务器上查询它以检查压缩功能的整体效率。

INNODB_CMP_PER_INDEX表报告有关各个表和索引的压缩活动的信息。此信息对于评估压缩效率和一次诊断一个表或索引的性能问题更有针对性和更有用。(因为每个InnoDB表都被表示为一个聚簇索引,所以MySQL在这种情况下并没有在表和索引之间做出很大的区分。)该 INNODB_CMP_PER_INDEX表确实涉及大量开销,所以它更适合于开发服务器,您可以在其中比较效果不同的工作量,数据和压缩设置。为防止意外强加这种监视开销,必须先启用 innodb_cmp_per_index_enabled 配置选项,然后才能查询 INNODB_CMP_PER_INDEX表。

要考虑的关键统计数据是执行压缩和解压缩操作所需的时间和数量。由于B-tree节点太满而无法包含修改后的压缩数据时,它会分割B-tree节点,因此比较 成功压缩操作的数量和整体操作的数量。基于信息 INNODB_CMPINNODB_CMP_PER_INDEX 表和整体应用程序性能以及硬件资源利用率,您可以对硬件配置进行更改,调整缓冲池的大小,选择不同的页面大小,或者选择一组不同的表来进行压缩。

如果压缩和解压缩所需的CPU时间很长,则更改为更快或多核的CPU可帮助用相同的数据,应用程序工作负载和一组压缩表提高性能。增加缓冲池的大小也可能有助于提高性能,以便更多未压缩的页面可以保留在内存中,从而减少仅以压缩形式解压缩存在于内存中的页面的需要。

大量的整体压缩操作(与数量INSERTUPDATEDELETE 在您的应用程序操作和数据库的大小)可能表明你的一些压缩的表都被更新过重的有效压缩。如果是这样,请选择一个更大的页面大小,或者选择要压缩的表格。

如果成功压缩操作(COMPRESS_OPS_OK)的数量占压缩操作总数的很高百分比(COMPRESS_OPS),那么系统可能表现良好。如果这个比例很低,那么MySQL正在重组,重新压缩和分割B树节点的次数往往比预期的要多。在这种情况下,避免压缩一些表,或者增加KEY_BLOCK_SIZE一些压缩表。您可以关闭导致压缩失败数量的表的压缩在你的申请中超过1%或2%。(在诸如数据加载的临时操作期间,这样的故障率可能是可接受的)。

14.9.1.5压缩如何对InnoDB表进行工作

本节介绍有关InnoDB表压缩的一些内部实现细节这里介绍的信息可能有助于调整性能,但不需要知道压缩的基本用法。

压缩算法

某些操作系统在文件系统级别实施压缩。文件通常分成固定大小的块,压缩成可变大小的块,这很容易导致碎片化。每次修改块内的某个内容时,整个块都会在写入磁盘之前被重新压缩。这些属性使这种压缩技术不适合在更新密集型数据库系统中使用。

MySQL在着名的zlib库的帮助下 实现了压缩,它实现了LZ77压缩算法。这种压缩算法在CPU利用率和数据大小的减少方面都是成熟,稳健和高效的。该算法是 无损 ”的,因此原始未压缩数据总是可以从压缩格式重建。LZ77压缩的工作方式是查找要压缩的数据中重复的数据序列。数据中值的模式决定了它压缩的程度,但典型的用户数据通常会压缩50%或更多。

注意

InnoDB zlib支持1.2.3版本库。

与应用程序执行的压缩或某些其他数据库管理系统的压缩功能不同,InnoDB压缩既适用于用户数据,也适用于索引。在许多情况下,索引可以占数据库总大小的40-50%或更多,因此这种差异是显着的。当数据集的压缩效果良好时,InnoDB数据文件( 文件 - 每表表 空间或常规表空间 .idb文件)的大小是未压缩大小的25%到50%,或者可能更小。取决于 工作量,这个较小的数据库可以反过来导致I / O的减少和吞吐量的增加,而对于CPU利用率的增加而言成本适中。您可以通过修改innodb_compression_level 配置选项来调整压缩级别和CPU开销之间的平衡

InnoDB数据存储和压缩

InnoDB表中的所有用户数据都存储在包含 B树索引( 聚簇索引)的页面中。在其他一些数据库系统中,这种类型的索引称为 索引组织表索引节点中的每一行都包含(用户指定的或系统生成的) 主键和表中所有其他列的值。

InnoDB表中的次级索引也是B树,包含值对:索引键和聚集索引中行的指针。指针实际上是表的主键值,如果需要除索引键和主键以外的列,则该键用于访问聚集索引。二级索引记录必须始终适合单个B树页面。

B-树节点的压缩(的集群和二级索引)是从压缩处理方式不同 溢出页用于存储长VARCHARBLOBTEXT列,如在以下部分中说明。

压缩B树页面

由于它们经常更新,所以B树页面需要特殊处理。将B树节点拆分的次数最小化以及将解压缩和重新压缩其内容的需求降至最低是非常重要的。

MySQL使用的一种技术是以未压缩的形式维护B树节点中的一些系统信息,从而便于某些就地更新。例如,这允许在没有任何压缩操作的情况下对行进行删除标记和删除。

另外,MySQL试图在更改索引页时避免不必要的解压缩和重新压缩索引页。在每个B-tree页面中,系统保留一个未压缩的 修改日志来记录对页面所做的更改。小记录的更新和插入可写入此修改日志而不需要整个页面被完全重构。

当修改日志的空间用完时,InnoDB解压页面,应用更改并重新压缩页面。如果再压缩失败(称为一个的情况 压缩破坏),B-树节点被分割,并重复该过程,直到更新或插入成功。

为避免写密集型工作负载(如OLTP 应用程序)频繁出现压缩失败,MySQL有时会在页面中保留一些空白区域(填充),以便修改日志尽早填满,页面重新压缩,同时仍有足够空间避免分裂它。随着系统跟踪页面拆分的频率,每个页面中留下的填充空间量也会变化。在频繁写入压缩表的繁忙服务器上,您可以调整 innodb_compression_failure_threshold_pctinnodb_compression_pad_pct_max 配置选项来微调此机制。

通常,MySQL要求InnoDB表中的每个B树页面至少可以容纳两条记录。对于压缩表,这个要求已经放宽。B树节点的叶页(无论是主键还是二级索引)只需要容纳一条记录,但该记录必须以非压缩形式适合每页修改日志。如果 innodb_strict_modeON,MySQL在CREATE TABLE期间检查最大行大小 CREATE INDEX如果该行不合适,则发出以下错误消息:ERROR HY000: Too big row

如果您在innodb_strict_modeOFF 时创建表 ,并且随后的INSERTor UPDATE语句尝试创建不符合压缩页大小的索引条目,则操作将失败,并显示ERROR 42000: Row size too large(此错误消息不会为记录太大的索引命名,或者提及索引记录的长度或特定索引页上的最大记录大小。)要解决此问题,请使用重建表 ALTER TABLE并选择更大压缩页面大小(KEY_BLOCK_SIZE),缩短任何列前缀索引,或完全禁用压缩ROW_FORMAT=DYNAMICROW_FORMAT=COMPACT

innodb_strict_mode不适用于也支持压缩表的常规表空间。通用表空间的表空间管理规则是独立于,严格执行的 innodb_strict_mode有关更多信息,请参见第13.1.19节“CREATE TABLESPACE语法”

压缩BLOB,VARCHAR和TEXT列

在一个InnoDB表,BLOBVARCHAR,和 TEXT列不属于主键的一部分可以被存储在单独分配 溢出页我们将这些列称为 离页列它们的值存储在单个链接的溢出页面列表中。

在创建的表ROW_FORMAT=DYNAMICROW_FORMAT=COMPRESSED,的值 BLOBTEXTVARCHAR列可以取决于它们的长度和整个行的长度存储完全关闭页。对于存储在页外的列,聚簇索引记录仅包含指向溢出页面的20字节指针,每列一个。是否有任何列存储在页外,取决于页面大小和行的总大小。当行太长而无法完全适应聚簇索引的页面时,MySQL会选择离页存储的最长列,直到该行适合聚集索引页面为止。如上所述,如果某行在压缩页面上不适合自身,则会发生错误。

注意

在创建的表ROW_FORMAT=DYNAMICROW_FORMAT=COMPRESSEDTEXT并且 BLOB是小于或等于40个字节的列总是存储在行。

在旧版本的MySQL中创建的表使用 Antelope文件格式,它仅支持ROW_FORMAT=REDUNDANTROW_FORMAT=COMPACT在这些格式中,MySQL存储第一768个字节的 BLOBVARCHARTEXT列在聚集索引记录与主密钥一起。768字节的前缀后跟一个20字节的指针,指向溢出页面,其中包含列值的其余部分。

当一个表格处于COMPRESSED格式时,写入溢出页面的所有数据都会按原样压缩; 也就是说,MySQL将zlib压缩算法应用于整个数据项。除数据以外,压缩溢出页面还包含一个未压缩的标题和尾部,其中包含页面校验和和下一个溢出页面的链接等。因此,能够更长时间来获得非常显著存储节省 BLOBTEXTVARCHAR列如果数据是高度可压缩,这是常有的文本数据的情况。图像数据,如JPEG通常已经被压缩,因此不会从被存储在压缩表中获益; 双倍压缩可能会浪费CPU周期,从而节省很少的空间或不节省空间

溢出页面与其他页面大小相同。包含存储在页外的10列的行占用10个溢出页面,即使列的总长度仅为8K字节。在未压缩的表中,十个未压缩的溢出页占用160K字节。在页面大小为8K的压缩表中,它们只占用80K字节。因此,对具有长列值的表使用压缩表格格式通常更有效。

对于文件的每个表 的表空间,采用16K压缩页面大小可以降低存储和I / O开销BLOBVARCHARTEXT列,因为这些数据往往压缩得很好,因此可能需要更少的溢出页,即使在B树节点他们自己的页面和未压缩的页面一样多。常规表空间不支持16K压缩页面大小(KEY_BLOCK_SIZE)。有关更多信息,请参见 第14.7.9节“InnoDB常规表空间”

压缩和InnoDB缓冲池

在压缩InnoDB表中,每个压缩页面(无论是1K,2K,4K还是8K)对应于16K字节的未压缩页面(如果innodb_page_size设置为更小的页面 )。要访问页面中的数据,MySQL会从磁盘读取压缩页面(如果该页面不在 缓冲池中),然后将页面解压缩为原始形式。本节介绍如何InnoDB管理相对于压缩表页面的缓冲池。

为了最大限度地减少I / O并减少解压缩页面的需要,缓冲池有时包含压缩和未压缩的数据库页面形式。为了为其他需要的数据库页面腾出空间,MySQL可以 从缓冲池中逐出未压缩页面,同时将压缩页面留在内存中。或者,如果页面在一段时间内未被访问,页面的压缩形式可能会被写入磁盘,以释放其他数据的空间。因此,在任何给定时间,缓冲池可能包含页面的压缩和未压缩形式,或者只包含页面的压缩形式,或者既不包含压缩形式。

MySQL会记录哪些页面保留在内存中,哪些使用最近最少使用(LRU)列表驱逐,以便 热点(频繁访问)的数据倾向于留在内存中。当访问压缩表时,MySQL使用自适应LRU算法在存储器中实现压缩和未压缩页面的适当平衡。这种自适应算法对系统是在I / O绑定还是 CPU绑定中运行很敏感方式。我们的目标是避免在CPU繁忙时花费太多的处理时间来解压缩页面,并且避免在CPU有可用于解压缩压缩页面(可能已存在于内存中)的空闲周期时执行多余的I / O操作。当系统受到I / O限制时,算法更喜欢驱逐一个页面的未压缩副本而不是两个副本,以便为其他磁盘页面留出更多空间成为内存驻留。当系统受到CPU限制时,MySQL更喜欢逐出压缩和未压缩页面,以便可以将更多内存用于页面,并且不需要仅以压缩形式解压缩内存中的数据。

压缩和InnoDB重做日志文件

在将压缩页面写入 数据文件之前,MySQL会将页面的副本写入重做日志(如果从上次写入数据库开始已重新压缩)。这样做是为了确保重做日志可用于 崩溃恢复,即使在不太可能的情况下zlib库升级,并且这种更改引入了压缩数据的兼容性问题。因此,一些日志文件的大小会增加 ,或者需要更频繁的 检查点,使用压缩时可以预期。日志文件大小或检查点频率的增加量取决于压缩页面以需要重组和压缩的方式修改的次数。

压缩表需要 梭子鱼文件格式。要在每个表文件表空间中创建压缩表, innodb_file_per_table必须启用并且innodb_file_format 必须设置为梭子鱼innodb_file_format在通用表空间中创建压缩表时,不依赖于 设置。有关更多信息,请参见第14.7.9节“InnoDB常规表空间”MySQL企业备份产品支持 的Barracuda文件格式。

14.9.1.6 OLTP工作负载的压缩

传统上,InnoDB 压缩功能主要建议用于只读或以读取为主的 工作负载,例如在 数据仓库 配置中。固态硬盘 存储设备的兴起虽然速度快但相对较小且昂贵,因此压缩对OLTP工作负载也很有吸引力 :高流量的交互式网站可通过使用压缩表来降低其存储需求和每秒I / O操作(IOPS)那些频繁的应用程序 INSERTUPDATEDELETE操作。

在MySQL 5.6中引入的配置选项使您可以调整压缩对特定MySQL实例的工作方式,重点在于编写密集型操作的性能和可伸缩性:

  • innodb_compression_level 可以让您调高或缩小压缩程度。较高的值可让您将更多数据放入存储设备,但压缩过程中CPU的开销会增加。当存储空间不重要时,较低的值可以减少CPU开销,或者您期望数据不是特别可压缩的。

  • innodb_compression_failure_threshold_pct 指定更新压缩表期间压缩失败的截止点 当这个阈值被传递时,MySQL开始在每个新的压缩页面中留下额外的空闲空间,动态调整空闲空间量直到页面大小百分比 innodb_compression_pad_pct_max

  • innodb_compression_pad_pct_max 可以调整每个页面中保留的最大空间量,以记录对压缩行的更改,而无需再次压缩整个页面。值越高,可以记录更多的变化而无需重新压缩页面。只有当指定百分比的压缩操作 在运行时失败时,MySQL才会为每个压缩表内的页面使用可变的可用空间量 ,这需要昂贵的操作来拆分压缩的页面。

  • innodb_log_compressed_pages 您可以禁用的写入图像 再压缩 页面重做日志对压缩数据进行更改时可能会发生重新压缩。此选项默认启用,以防止zlib在恢复期间使用不同版本的压缩算法时可能发生的损坏 如果您确定 zlib版本不会更改,请禁用 innodb_log_compressed_pages 以减少修改压缩数据的工作负载的重做日志生成。

由于使用压缩数据有时需要同时在页面内存中保存压缩版本和未压缩版本,因此,在使用OLTP样式工作负载压缩时,请准备好增加innodb_buffer_pool_size 配置选项的值

14.9.1.7 SQL压缩语法警告和错误

本节介绍在将表压缩功能与每个表文件的表 空间和常规表空间配合使用时可能遇到的语法警告和错误

针对每个文件表空间的SQL压缩语法警告和错误

innodb_strict_mode被使能(默认值),指定 ROW_FORMAT=COMPRESSEDKEY_BLOCK_SIZECREATE TABLEALTER TABLE 语句如果产生以下错误 innodb_file_per_table被禁用,或者如果 innodb_file_format被设定为 Antelope,而不是 Barracuda

错误1031(HY000):'t1'的表存储引擎没有这个选项
注意

如果当前配置不允许使用压缩表,则不会创建该表。

innodb_strict_mode禁用时, 如果禁用,则指定ROW_FORMAT=COMPRESSEDKEY_BLOCK_SIZEin CREATE TABLE或者ALTER TABLE 语句会生成以下警告 innodb_file_per_table

MySQL的> SHOW WARNINGS;
+ --------- + ------ + -------------------------------- ------------------------------- +
| 级别| 代码| 留言|
+ --------- + ------ + -------------------------------- ------------------------------- +
| 警告| 1478 | InnoDB:KEY_BLOCK_SIZE需要innodb_file_per_table。|
| 警告| 1478 | InnoDB:忽略KEY_BLOCK_SIZE = 4。|
| 警告| 1478 | InnoDB:ROW_FORMAT = COMPRESSED需要innodb_file_per_table。|
| 警告| 1478 | InnoDB:假设ROW_FORMAT = DYNAMIC。|
+ --------- + ------ + -------------------------------- ------------------------------- +

如果类似的警告发出 innodb_file_format设置为 Antelope,而不是 Barracuda

注意

这些消息只是警告,而不是错误,并且表格是在没有压缩的情况下创建的,就好像这些选项没有指定一样。

非严格的行为可让您导入 mysqldump文件到不支持压缩表,即使源数据库包含压缩表的数据库。在这种情况下,MySQL创建表 ROW_FORMAT=COMPACT而不是阻止操作。

要将转储文件导入到新数据库中,并使表格在原始数据库中存在时重新创建,请确保服务器具有适当的配置参数 innodb_file_formatinnodb_file_per_table

该属性KEY_BLOCK_SIZE仅在ROW_FORMAT被指定为 COMPRESSED或被省略时才被允许KEY_BLOCK_SIZE使用任何其他 指定会 ROW_FORMAT生成警告,您可以使用该警告进行查看SHOW WARNINGS但是,表格是非压缩的; 指定的 KEY_BLOCK_SIZE被忽略)。

水平 信息
警告 1478 InnoDB: ignoring KEY_BLOCK_SIZE=n unless ROW_FORMAT=COMPRESSED.

如果在innodb_strict_mode启用时运行 ,a KEY_BLOCK_SIZEROW_FORMAT其他 任何组合都会 COMPRESSED生成错误,而不是警告,并且不会创建表。

表14.7“ROW_FORMAT和KEY_BLOCK_SIZE选项” 提供了or 一起使用的概述ROW_FORMATKEY_BLOCK_SIZE选项 CREATE TABLEALTER TABLE

表14.7 ROW_FORMAT和KEY_BLOCK_SIZE选项

选项 使用说明 描述
ROW_FORMAT=​REDUNDANT 在MySQL 5.0.3之前使用的存储格式 效率低于ROW_FORMAT=COMPACT; 为了向后兼容
ROW_FORMAT=​COMPACT 自MySQL 5.0.3以来的默认存储格式 在聚簇索引页中存储长字段值的前缀768字节,其余字节存储在溢出页中
ROW_FORMAT=​DYNAMIC 文件每表的表空间需要 innodb_file​_format=Barracuda 如果它们合适,则将值存储在聚集索引页面内; 如果不是,则只存储一个指向溢出页面的20字节指针(无前缀)
ROW_FORMAT=​COMPRESSED 文件每表的表空间需要 innodb_file​_format=Barracuda 使用zlib压缩表和索引
KEY_BLOCK_​SIZE=n 文件每表的表空间需要 innodb_file​_format=Barracuda 指定1,2,4,8或16千字节的压缩页面大小; 意味着 ROW_FORMAT=COMPRESSED对于一般的表空间,不允许KEY_BLOCK_SIZE等于InnoDB页面大小

表14.8“InnoDB严格模式为OFF时的CREATE / ALTER TABLE警告和错误” 汇总了CREATE TABLEor或者 ALTER TABLE语句上的某些配置参数和选项组合出现的错误条件 ,以及这些选项如何显示在输出中SHOW TABLE STATUS

innodb_strict_modeOFF时,MySQL创建或改变该表中,但如下所示忽略某些设置。您可以在MySQL错误日志中看到警告消息。如果 innodb_strict_modeON,这些指定的选项组合产生的错误,表中没有创建或修改。要查看错误情况的完整描述,请发布以下 SHOW ERRORS语句:例如:

mysql> CREATE TABLE x (id INT PRIMARY KEY, c INT)

- >ENGINE=INNODB KEY_BLOCK_SIZE=33333;

错误1005(HY000):无法创建表'test.x'(错误号:1478)

MySQL的> SHOW ERRORS;
+ ------- + ------ + ---------------------------------- --------- +
| 级别| 代码| 留言|
+ ------- + ------ + ---------------------------------- --------- +
| 错误| 1478 | InnoDB:无效KEY_BLOCK_SIZE = 33333。|
| 错误| 1005 | 无法创建表'test.x'(errno:1478)|
+ ------- + ------ + ---------------------------------- --------- +

表14.8 InnoDB严格模式关闭时的CREATE / ALTER TABLE警告和错误

句法 警告或错误情况 结果ROW_FORMAT如图所示SHOW TABLE STATUS
ROW_FORMAT=REDUNDANT 没有 REDUNDANT
ROW_FORMAT=COMPACT 没有 COMPACT
ROW_FORMAT=COMPRESSEDROW_FORMAT=DYNAMIC或被 KEY_BLOCK_SIZE指定 忽略文件的每个表的表空间,除非双方 启用。一般的表空间支持所有行格式(有一些限制),无论 设置。请参见14.7.9节,“InnoDB常规表空间”innodb_file_format=Barracudainnodb_file_per_tableinnodb_file_formatinnodb_file_per_table the default row format for file-per-table tablespaces; the specified row format for general tablespaces
KEY_BLOCK_SIZE指定了无效(不是1,2,4,8或16) KEY_BLOCK_SIZE 被忽略 指定的行格式或默认行格式
ROW_FORMAT=COMPRESSEDKEY_BLOCK_SIZE指定有效 没有; KEY_BLOCK_SIZE指定使用 COMPRESSED
KEY_BLOCK_SIZE与指定的 REDUNDANTCOMPACTDYNAMIC行格式 KEY_BLOCK_SIZE 被忽略 REDUNDANTCOMPACT或者 DYNAMIC
ROW_FORMAT是没有一个 REDUNDANTCOMPACTDYNAMICCOMPRESSED 如果被MySQL解析器识别,则被忽略。否则,会发出错误。 默认的行格式或N / A

innodb_strict_modeON时,MySQL拒绝无效 ROW_FORMATKEY_BLOCK_SIZE参数问题的错误。innodb_strict_modeOFF时,MySQL发出警告,而不是被忽略的参数无效的错误。 innodb_strict_modeON 默认的。

innodb_strict_modeON时,MySQL拒绝无效 ROW_FORMATKEY_BLOCK_SIZE参数。为了与早期版本的MySQL兼容,默认情况下严格模式未启用; 相反,MySQL会为忽略的无效参数发出警告(而不是错误)。

无法看到所选的 KEY_BLOCK_SIZE使用SHOW TABLE STATUS该语句SHOW CREATE TABLE显示KEY_BLOCK_SIZE (即使它在创建表时被忽略)。MySQL的真实压缩页面大小不能显示。

常规表空间的SQL压缩语法警告和错误
  • 如果FILE_BLOCK_SIZE在创建表空间时没有为常规表空间定义,则表空间不能包含压缩表。如果尝试添加压缩表,则会返回错误,如以下示例中所示:

    MySQL的> CREATE TABLESPACE `ts1` ADD DATAFILE 'ts1.ibd' Engine=InnoDB;
    
    MySQL的> CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts1 ROW_FORMAT=COMPRESSED
           KEY_BLOCK_SIZE=8;
    错误1478(HY000):InnoDB:Tablespace`ts1`不能包含COMPRESSED表
    
  • 试图向KEY_BLOCK_SIZE常规表空间添加一个无效 的表会返回一个错误,如下例所示:

    MySQL的> CREATE TABLESPACE `ts2` ADD DATAFILE 'ts2.ibd' FILE_BLOCK_SIZE = 8192 Engine=InnoDB;
      
    MySQL的> CREATE TABLE t2 (c1 INT PRIMARY KEY) TABLESPACE ts2 ROW_FORMAT=COMPRESSED
           KEY_BLOCK_SIZE=4;
    错误1478(HY000):InnoDB:表空间ts2`使用块大小8192,不能
    包含一个物理页面大小为4096的表格

    对于一般的表空间, KEY_BLOCK_SIZE表的大小必须等于FILE_BLOCK_SIZE表空间除以1024.例如,如果 FILE_BLOCK_SIZE表空间的大小是8192,KEY_BLOCK_SIZE则表的大小必须是8。

  • 尝试将未压缩的行格式的表添加到配置为存储压缩表的常规表空间中时会返回错误,如以下示例所示:

    MySQL的> CREATE TABLESPACE `ts3` ADD DATAFILE 'ts3.ibd' FILE_BLOCK_SIZE = 8192 Engine=InnoDB;
    
    MySQL的> CREATE TABLE t3 (c1 INT PRIMARY KEY) TABLESPACE ts3 ROW_FORMAT=COMPACT;
    错误1478(HY000):InnoDB:表空间ts3`使用块大小8192,不能
    包含一个物理页面大小为16384的表格

innodb_strict_mode不适用于一般的表空间。通用表空间的表空间管理规则是独立于,严格执行的 innodb_strict_mode有关更多信息,请参见第13.1.19节“CREATE TABLESPACE Syntax”

有关在一般表空间中使用压缩表的更多信息,请参见第14.7.9节“InnoDB常规表空间”

14.9.2 InnoDB页面压缩

InnoDB支持驻留在每个表文件表 空间中的表的页面级压缩 这个功能被称为透明页面压缩通过COMPRESSION使用CREATE TABLE指定属性 来启用页面压缩ALTER TABLE支持的压缩算法包括ZlibLZ4

支持的平台

页面压缩需要稀疏文件和打孔支持。在Windows上使用NTFS支持页面压缩,以及在内核级别提供打孔支持的MySQL支持的Linux平台的以下子集上:

  • RHEL 7以及使用内核版本3.10.0-123或更高版本的派生分发版

  • OEL 5.10(UEK2)内核版本2.6.39或更高版本

  • OEL 6.5(UEK3)内核版本为3.8.13或更高版本

  • OEL 7.0内核版本为3.8.13或更高版本

  • SLE11内核版本3.0-x

  • SLE12内核版本3.12-x

  • OES11内核版本3.0-x

  • Ubuntu 14.0.4 LTS内核版本3.13或更高

  • Ubuntu 12.0.4 LTS内核版本3.2或更高

  • Debian 7内核版本3.2或更高

注意

给定Linux发行版的所有可用文件系统可能不支持打孔。

页面压缩如何工作

当页面被写入时,它使用指定的压缩算法进行压缩。压缩数据被写入磁盘,打孔机制从页面末尾释放空白块。如果压缩失败,数据将按原样写出。

Linux上的打孔大小

在Linux系统上,文件系统块大小是用于打孔的单位大小。因此,页面压缩仅适用于页面数据可以压缩到小于或等于 InnoDB页面大小减去文件系统块大小的大小。例如,如果 innodb_page_size=16K文件系统块大小为4K,则页面数据必须压缩到小于或等于12K才能进行打孔。

Windows上的打孔尺寸

在Windows系统上,稀疏文件的基础架构基于NTFS压缩。打孔大小是NTFS压缩单位,是NTFS簇大小的16倍。下表中显示了簇大小及其压缩单元:

表14.9 Windows NTFS群集大小和压缩单位

簇的大小 压缩单元
512字节 8 KB
1 KB 16 KB
2 KB 32 KB
4 KB 64 KB

Windows系统上的页面压缩仅适用于页面数据可以压缩到小于或等于 InnoDB页面大小减去压缩单元大小的大小。

默认的NTFS簇大小为4K,压缩单元大小为64K。这意味着页面压缩对于开箱即用的Windows NTFS配置没有好处,因为最大值 innodb_page_size也是64K。

为了在Windows上工作页面压缩,必须创建文件系统的簇大小小于4K,并且 innodb_page_size必须至少是压缩单元大小的两倍。例如,对于在Windows上工作的页面压缩,您可以创建512字节的群集大小(压缩单元为8KB)的文件系统,并InnoDB使用innodb_page_size16K或更大值进行初始化

启用页面压缩

要启用页面压缩,请COMPRESSIONCREATE TABLE语句中指定 属性 例如:

CREATE TABLE t1(c1 INT)COMPRESSION =“zlib”;

您也可以在ALTER TABLE语句中启用页面压缩 但是, ALTER TABLE ... COMPRESSION只更新表空间压缩属性。写入设置新压缩算法后发生的表空间使用新设置,但要将新压缩算法应用于现有页面,必须使用重建表OPTIMIZE TABLE

ALTER TABLE t1 COMPRESSION =“zlib”;
OPTIMIZE TABLE t1;

禁用页面压缩

要禁用页面压缩,请COMPRESSION=None使用 设置 ALTER TABLE写入设置后COMPRESSION=None不再使用页面压缩的表空间 要解压缩现有页面,必须OPTIMIZE TABLE在设置之后使用重建表格COMPRESSION=None

ALTER TABLE t1 COMPRESSION =“None”;
OPTIMIZE TABLE t1;

页面压缩元数据

页面压缩元数据位于 INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES 表格中的以下列中:

  • FS_BLOCK_SIZE:文件系统块大小,即用于打孔的单位大小。

  • FILE_SIZE:文件的表观大小,表示文件的最大大小,未压缩。

  • ALLOCATED_SIZE:文件的实际大小,即磁盘上分配的空间量。

注意

在类Unix系统上,以字节为单位显示明显的文件大小(相当于 )。要查看磁盘上分配的实际空间量(等同于 ),请使用选项以字节而不是块打印分配的空间,以便将其与输出进行比较 ls -l tablespace_name.ibdFILE_SIZEALLOCATED_SIZEdu --block-size=1 tablespace_name.ibd--block-size=1ls -l

使用SHOW CREATE TABLE查看当前页面压缩设置(ZlibLz4,或None)。表格可能包含具有不同压缩设置的页面混合。

在以下示例中,从表中检索employees表的页面压缩元数据 INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES

#使用Zlib页面压缩功能创建员工表

CREATE TABLE employees(
    emp_no INT NOT NULL,
    birth_date DATE NOT NULL,
    first_name VARCHAR(14)NOT NULL,
    last_name VARCHAR(16)NOT NULL,
    性别ENUM('M','F')NOT NULL,  
    hire_date DATE NOT NULL,
    PRIMARY KEY(emp_no)
)COMPRESSION =“zlib”;

#插入数据(未显示)
  
#在INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES中查询页面压缩元数据
  
MySQL的> SELECT SPACE, NAME, FS_BLOCK_SIZE, FILE_SIZE, ALLOCATED_SIZE FROM
       INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE NAME='employees/employees'\G
*************************** 1. row ******************** *******
空间:45
名称:员工/员工
FS_BLOCK_SIZE:4096
FILE_SIZE:23068672
ALLOCATED_SIZE:19415040

员工表的页面压缩元数据显示明显的文件大小为23068672字节,而实际文件大小(使用页面压缩)为19415040字节。文件系统块大小为4096字节,这是用于打孔的块大小。

页面压缩限制和使用说明

  • 如果文件系统块大小(或Windows上的压缩单元大小)* 2>,则禁用页面压缩 innodb_page_size

  • 页面压缩不支持驻留在共享表空间中的表,其中包括系统表空间,临时表空间和常规表空间。

  • 撤消日志表空间不支持页面压缩。

  • 重做日志页面不支持页面压缩。

  • 用于空间索引的R树页面不被压缩。

  • 属于压缩表(ROW_FORMAT=COMPRESSED)的页面保持原样。

  • 恢复期间,更新的页面以未压缩的形式写出。

  • 在不支持所使用的压缩算法的服务器上加载页面压缩的表空间会导致I / O错误。

  • 在降级到不支持页面压缩的早期版本的MySQL之前,解压缩使用页面压缩功能的表。要解压缩一个表,运行 ALTER TABLE ... COMPRESSION=NoneOPTIMIZE TABLE

  • 如果所使用的压缩算法在两台服务器上均可用,则可以在Linux和Windows服务器之间复制页面压缩的表空间。

  • 将页面压缩的表空间文件从一台主机移动到另一台主机时,保留页面压缩需要一个保存稀疏文件的实用程序。

  • 在NVMFS的Fusion-io硬件上比在其他平台上可以实现更好的页面压缩,因为NVMFS旨在利用打孔功能。

  • 使用具有较大InnoDB页面大小和较小文件系统块大小的页面压缩功能 可能导致写入放大。例如,InnoDB具有4KB文件系统块大小的64KB 的最大页面大小可以改善压缩,但是也可能增加对缓冲池的需求,导致增加的I / O和潜在的写入放大。

14.10 InnoDB文件格式管理

随着InnoDB发展,与以前版本不兼容的数据文件格式InnoDB有时需要支持新功能。为了帮助管理升级和降级情况下的兼容性以及运行不同版本MySQL的系统,InnoDB使用命名文件格式。InnoDB目前支持两种命名的文件格式,AntelopeBarracuda

本节讨论InnoDB为新InnoDB启用文件格式,验证MySQL版本之间不同文件格式的兼容性,以及识别正在使用的文件格式。

InnoDB文件格式设置不适用于存储在 一般表空间中的表常规表空间提供对所有行格式和相关功能的支持。有关更多信息,请参见 第14.7.9节“InnoDB常规表空间”

注意

以下文件格式配置参数具有新的默认值:

以下文件格式配置参数已弃用,并可能在未来版本中删除:

提供的文件格式配置参数用于创建与InnoDBMySQL 5.1 早期版本兼容的表 现在MySQL 5.1已经到了产品生命周期的最后阶段,这些参数不再需要了。

14.10.1启用文件格式

innodb_file_format 配置选项使InnoDB文件格式 文件的每个表的 表空间。

Barracuda是默认 innodb_file_format设置。在早期版本中,默认文件格式为 Antelope

注意

innodb_file_format 配置选项已被弃用,并可能在将来的版本中删除。有关更多信息,请参见 第14.10节“InnoDB文件格式管理”

您可以innodb_file_format在启动mysqld时或在选项文件中(my.cnf在Unix上, my.ini在Windows上)设置命令行中的值 您还可以使用SET GLOBAL语句动态更改它

SET GLOBAL innodb_file_format =梭鱼;

使用说明

14.10.2验证文件格式兼容性

InnoDB集成了多项检查功能,以防止在InnoDB数据文件上使用较新的文件格式运行旧版MySQL服务器时可能发生的崩溃和数据损坏。这些检查在服务器启动时以及第一次访问表时进行。本节介绍这些检查,如何控制它们,以及可能出现的错误和警告条件。

向后兼容性

当使用InnoDB的最新版本(InnoDB的MySQL 5.5及更高版本)以及旧版本(MySQL 5.1或更早版本,内置InnoDB而不是InnoDB插件)时,您只需考虑向后文件格式的兼容性。为了最大限度地减少兼容性问题的机会,您可以在InnoDB插件上标准化所有MySQL 5.1和更早版本的数据库服务器。

一般来说,较新版本的InnoDB可能会创建一个表或索引,无法安全地使用InnoDB的旧版本进行读取或写入,而没有崩溃,挂起,错误结果或损坏的风险。InnoDB包含防范这些情况的机制,并帮助保持数据库文件和InnoDB版本之间的兼容性。通过这种机制,您可以利用InnoDB版本的一些新功能(例如性能改进和错误修复),并保留将数据库与旧版InnoDB一起使用的选项,防止意外使用创建向下的新功能不兼容的磁盘文件。

如果一个版本的InnoDB支持特定的文件格式(无论该格式是否为默认格式),则可以查询和更新任何需要该格式或更早格式的表格。基于启用的特定文件格式,仅限使用新功能创建新表的限制。相反,如果表空间包含使用不受支持的文件格式的表或索引,则即使对于读取访问,也不能访问它。

InnoDB表空间降级为早期的Antelope文件格式的唯一方法是将数据复制到使用较早格式的表空间中的新表中。

确定现有InnoDB表空间文件格式的最简单方法是使用该SHOW TABLE STATUS命令或查询表来检查其包含的表的属性INFORMATION_SCHEMA.TABLES如果该 Row_format表的报告为 'Compressed''Dynamic',则包含该表的表空间支持梭子鱼格式。

内部细节

每个InnoDB文件 - 每表表空间(由*.ibd文件表示 )文件都标有文件格式标识符。系统表空间(由ibdata文件表示 )被标记为一组InnoDB数据库文件中使用最高文件格式,并且在打开文件时检查该标记。

使用Barracuda文件格式的标识符 创建压缩表或带有表的表 ROW_FORMAT=DYNAMIC,可以更新相应的每个.ibd文件文件的文件头和InnoDB数据字典中的表类型。从那时起,该表不能用于不支持Barracuda文件格式的InnoDB版本。为防止异常行为,InnoDB在表打开时执行兼容性检查。(在许多情况下,ALTER TABLE 语句重新创建一个表并因此改变它的属性。在第14.13.1节“在线DDL概述”中描述了添加或删除索引而不重建表的特殊情况 。)

一般的表空间也由*.ibd文件表示 ,支持羚羊和梭子鱼文件格式。有关常规表空间的更多信息,请参见 第14.7.9节“InnoDB常规表空间”

ib文件集的定义

为了避免混淆,为了讨论的目的,我们将术语ib-file set定义为InnoDB作为一个单元管理的一组操作系统文件。ib文件集包括以下文件:

  • ibdata 包含内部系统信息(包括内部目录和撤消信息)并可能包含用户数据和索引 的系统表空间(一个或多个文件)。

  • 零个或多个单表表空间(也称为每个表文件文件,命名*.ibd 文件)。

  • InnoDB日志文件; 通常是两个,ib_logfile0 而且ib_logfile1用于崩溃恢复和备份。

一个IB-文件集不包括相应的 .frm包含约InnoDB表的元数据文件。这些.frm文件由MySQL创建和管理,有时可能与InnoDB中的内部元数据不同步。

即使来自多个数据库的多个表也可以存储在一个ib文件集 ”中(在MySQL中, 数据库是表的逻辑集合,其他系统称为模式目录。)

14.10.2.1 InnoDB启动时的兼容性检查

为了防止InnoDB打开ib文件集时可能发生的崩溃或数据损坏,它会检查它是否完全支持ib文件集内使用的文件格式。如果系统在崩溃或快速关闭 (即innodb_fast_shutdown大于零)之后重新启动,则可能有磁盘上的数据结构(例如重做或撤销条目或双重写入页面)也处于 太新格式为当前软件。在恢复过程中,如果访问这些数据结构,可以对数据文件造成严重损坏。文件格式的启动检查在任何恢复过程开始之前发生,从而防止新表的一致性问题或MySQL服务器的启动问题。

从版本InnoDB 1.0.1开始,系统表空间会记录任何属于ib文件集的表空间中的任何表所使用最高文件格式的标识符或标记针对这种文件格式标签检查由配置参数来控制 innodb_file_format_check,这是ON通过默认。

如果系统表空间中的文件格式标记比当前正在执行的特定软件支持的最高版本更新或更高,并且如果 innodb_file_format_checkON,则在服务器启动时发出以下错误:

InnoDB:错误:系统表空间位于
该版本不支持的文件格式

您也可以设置 innodb_file_format为文件格式名称。如果当前软件不支持指定的文件格式,则会阻止InnoDB启动。它还将高水位设置为您指定的值。innodb_file_format_check如果您手动降级 ib文件集中的所有表,设置的能力 是有用的(对未来的版本) 然后,如果您随后使用InnoDB的较早版本访问ib文件集,则可以在启动时依赖文件格式检查。

在某些有限的情况下,您可能需要启动服务器并使用ib文件集,该文件集采用新文件格式,而您所使用的软件不支持该文件格式。如果您将配置参数设置 innodb_file_format_checkOFF,InnoDB将打开数据库,但在错误日志中发出以下警告消息:

InnoDB:警告:系统表空间位于
该版本不支持的文件格式
注意

这是一个危险的设置,因为它允许恢复过程运行,如果以前的关闭是崩溃或快速关闭,可能会损坏数据库如果您确定先前的关闭已完成 则只应设置 innodb_file_format_check,以便基本上不会发生恢复过程。 OFFinnodb_fast_shutdown=0

该参数 innodb_file_format_check 仅影响打开数据库时发生的情况,而不是随后发生。相反,参数 innodb_file_format(启用特定格式)仅确定是否可以使用启用的格式创建新表,并且不影响数据库是否可以打开。

文件格式标记是一个高水位标记,因此在服务器启动之后,如果创建格式的表或者读取或写入现有表(假设其格式为支持的)。如果以比运行软件支持的格式更高的格式访问现有表,则不会更新系统表空间标记,但将应用表级别兼容性检查(并发出错误),如 第14.10.2.2节“打开表格时的兼容性检查“任何时候更新高水位标记的值 innodb_file_format_check也会更新,因此该命令将SELECT @@innodb_file_format_check;显示当前已打开的ib文件集中已知由表使用且当前正在执行的软件支持的最新文件格式的名称。

14.10.2.2打开表格时的兼容性检查

当首次访问表时,InnoDB(包括InnoDB 1.0之前的一些版本)将检查表中存储的表空间的文件格式是否完全受支持。此检查可防止遇到使用太新数据结构的表时发生的崩溃或损坏

所有使用发行版支持的任何文件格式的表都可以读取或写入(假设用户具有足够的权限)。innodb_file_format即使给定版本支持文件格式,系统配置参数的设置 也可以防止创建使用特定文件格式的新表。这样的设置可能用于保持向后兼容性,但它不会阻止访问任何使用支持格式的表。

如果在创建表时使用了新的文件格式,那么早于5.0.21的MySQL版本不能可靠地使用由较新版本创建的数据库文件。为了防止各种错误情况或损坏,InnoDB在打开文件时(例如首次访问表格时)检查文件格式兼容性。如果当前运行的InnoDB版本不支持InnoDB数据字典中表类型标识的文件格式,则MySQL报告以下错误:

错误1146(42S02):表' testt1'不存在

InnoDB还会向错误日志写入消息:

InnoDB:表test/ t1:未知表类型33

表类型应该等于表空间标志,它包含第14.10.3节“识别正在使用的文件格式”中讨论的文件格式版本

MySQL 4.1之前的InnoDB版本不包括数据库文件中的表格格式标识符,并且MySQL 5.0.21之前的版本未包含表格格式兼容性检查。因此,如果在5.0.21之前的InnoDB版本中使用新文件格式的表格,则无法确保正确的操作。

InnoDB 1.0和更高版本(表空间标记和运行时检查)中的文件格式管理功能允许InnoDB尽快验证软件的运行版本是否可以正确处理数据库中存在的表。

如果允许InnoDB打开一个包含不支持的格式的数据库(通过设置参数 innodb_file_format_checkOFF),本节中描述的表级检查仍然适用。

强烈建议 用户不要使用包含Barracuda文件格式表的数据库文件,而InnoDB版本比InnoDB插件早于MySQL 5.1。可能重建这些表格以使用Antelope格式。

14.10.3识别正在使用的文件格式

如果使用 配置选项启用不同的文件格式innodb_file_format,则更改仅适用于新创建的表格。另外,当您创建新表时,包含该表的表空间将标记为支持表的功能所需最早最简单 ”的文件格式。例如,如果启用 Barracuda文件格式并创建不使用动态或压缩行格式的新表,则包含该表的新表空间将标记为使用 Antelope文件格式。

识别给定表格使用的文件格式很容易。Antelope如果报告的行格式SHOW TABLE STATUSCompact表格使用文件格式RedundantBarracuda如果报告的行格式SHOW TABLE STATUSCompressed表格使用文件格式Dynamic

MySQL的> SHOW TABLE STATUS\G
*************************** 1. row ******************** *******
           名称:t1
         引擎:InnoDB
        版本:10
     Row_format:紧凑
           行数:0
 Avg_row_length:0
    Data_length:16384
Max_data_length:0
   Index_length:16384
      Data_free:0
 Auto_increment:1
    Create_time:2014-11-03 13:32:10
    Update_time:NULL
     Check_time:NULL
      整理:latin1_swedish_ci
       校验和:NULL
 Create_options:
        评论:

您还可以使用InnoDB INFORMATION_SCHEMA表格识别给定表格或表格空间使用的文件格式例如:

MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME='test/t1'\G
*************************** 1. row ******************** *******
     TABLE_ID:44
         NAME:test / t1
         FLAG:1
       N_COLS:6
        空间:30
  FILE_FORMAT:羚羊
   ROW_FORMAT:紧凑
ZIP_PAGE_SIZE:0
  
MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE NAME='test/t1'\G
*************************** 1. row ******************** *******
        空间:30
         NAME:test / t1
         FLAG:0
  FILE_FORMAT:羚羊
   ROW_FORMAT:紧凑或冗余
    PAGE_SIZE:16384
ZIP_PAGE_SIZE:0

14.10.4修改文件格式

每个InnoDB表空间文件(名称匹配 *.ibd)都使用用于创建表和索引的文件格式进行标记。修改文件格式的方法是重新创建表及其索引。重新创建表及其索引的最简单方法是在每个要修改的表上使用以下命令:

ALTER TABLE tROW_FORMAT = format_name;

如果您将文件格式修改为降级为较旧的MySQL版本,则表格存储格式中可能存在不兼容的情况,需要执行其他步骤。有关降级到以前的MySQL版本的信息,请参见 第2.11.2节“降级MySQL”

14.11 InnoDB行存储和行格式

本节讨论InnoDB功能如表 压缩,长变长列值的离页存储和大索引键前缀(innodb_large_prefix)是如何由InnoDB表格的行格式控制的它还讨论了选择正确行格式的注意事项,以及MySQL版本之间行格式的兼容性。

14.11.1 InnoDB行存储概述

行和相关列的存储会影响查询和DML操作的性能。当更多的行适合单个磁盘页面时,查询和索引查找可以更快地工作,InnoDB缓冲池中所需的缓存内存更少,并且需要更少的I / O来为数字和短字符串列写出更新的值。

每个InnoDB表中的数据分为多 构成每个表的页面被排列在称为B树索引的树数据结构中 表格数据和 二级索引都使用这种类型的结构。表示整个表的B树索引称为 聚集索引,根据主键组织 索引索引数据结构的节点包含该行(对于聚集索引)或索引列和主键列(对于二级索引)中的所有列的值。

可变长度列是此规则的一个例外。诸如BLOBVARCHAR 太长而不适合B树页面的列被存储在被称为溢出页面的单独分配的磁盘 页面上我们将这些列称为离页列这些列的值存储在单个链接的溢出页面列表中,每个这样的列都有自己的一个或多个溢出页面的列表。在某些情况下,长列值的所有或前缀都存储在B-树中,以避免浪费存储空间并消除读取单独页面的需要。

以下各节介绍如何配置InnoDB表格的行格式 以控制如何存储可变长度列值。行格式配置还确定表压缩功能和大型索引键前缀功能(innodb_large_prefix的可用性

14.11.2指定表格的行格式

默认行格式由innodb_default_row_format默认值定义 DYNAMICROW_FORMAT表格选项未明确定义或 ROW_FORMAT=DEFAULT指定时,将使用默认行格式

表格的行格式可以使用ROW_FORMATa CREATE TABLEALTER TABLE语句中表格选项 明确定义 例如:

CREATE TABLE t1(c1 INT)ROW_FORMAT = DYNAMIC;

明确定义的ROW_FORMAT设置将覆盖隐式默认值。指定 ROW_FORMAT=DEFAULT等同于使用隐式默认值。

innodb_default_row_format 选项可以动态设置:

MySQL的> SET GLOBAL innodb_default_row_format=DYNAMIC;

有效的innodb_default_row_format 选项包括DYNAMICCOMPACT,和REDUNDANTCOMPRESSED不支持在系统表空间中使用行格式不能被定义为默认值。它只能在a CREATE TABLEALTER TABLE语句中明确指定 试图设置innodb_default_row_formatCOMPRESSED返回错误:

MySQL的> SET GLOBAL innodb_default_row_format=COMPRESSED;
错误1231(42000):变量'innodb_default_row_format'
不能设置为'COMPRESSED'的值

新创建的表格使用在未明确指定选项或使用选项innodb_default_row_format定义的行格式 例如,以下 语句使用由定义的行格式 ROW_FORMATROW_FORMAT=DEFAULTCREATE TABLEinnodb_default_row_format

CREATE TABLE t1(c1 INT);
CREATE TABLE t2(c1 INT)ROW_FORMAT = DEFAULT;

如果ROW_FORMAT未明确指定选项或者何时ROW_FORMAT=DEFAULT使用选项,则重建表的任何操作也会静默地将表格的行格式更改为由其定义的格式 innodb_default_row_format

表重建操作包括ALTER TABLE使用 操作ALGORITHM=COPYALTER TABLE使用ALGORITHM=INPLACE需要重建表的操作 有关DDL操作的联机状态的概述,请参阅表14.10,“DDL操作的联机状态”。 OPTIMIZE TABLE也是一个桌子重建操作。

以下示例演示了一个表重建操作,它默默更改未创建明确定义的行格式而创建的表格的行格式。

MySQL的> SELECT @@innodb_default_row_format;
+ ----------------------------- +
| @@ innodb_default_row_format |
+ ----------------------------- +
| 动态|
+ ----------------------------- +

MySQL的> CREATE TABLE t1 (c1 INT);

MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/t1' \G
*************************** 1. row ******************** *******
     TABLE_ID:54
         NAME:test / t1
         国旗:33
       N_COLS:4
        空间:35
  FILE_FORMAT:梭子鱼
   ROW_FORMAT:动态
ZIP_PAGE_SIZE:0
   SPACE_TYPE:单一

MySQL的> SET GLOBAL innodb_default_row_format=COMPACT;

MySQL的> ALTER TABLE t1 ADD COLUMN (c2 INT);

MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/t1' \G
*************************** 1. row ******************** *******
     TABLE_ID:55
         NAME:test / t1
         FLAG:1
       N_COLS:5
        空间:36
  FILE_FORMAT:羚羊
   ROW_FORMAT:紧凑
ZIP_PAGE_SIZE:0
   SPACE_TYPE:单一

从改变现有表的行格式之前,请考虑以下潜在的问题REDUNDANTCOMPACTDYNAMIC

要查看表格的行格式,请发出 SHOW TABLE STATUS语句或查询INFORMATION_SCHEMA.TABLES

SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE'test / t1'\ G

InnoDB表格 的行格式决定了其物理行结构。有关更多信息请参见 第14.8.1.2节“InnoDB表的物理行结构”

14.11.3动态和压缩行格式

当使用ROW_FORMAT=DYNAMIC or 创建表时ROW_FORMAT=COMPRESSEDInnoDB可以将完全离页的长可变长度列值(for VARCHARVARBINARYand BLOBTEXTtype)存储在聚合索引记录中,其中聚集索引记录仅包含指向溢出页面的20字节指针。InnoDB还将长度大于或等于768字节的固定长度字段编码为可变长度字段。例如, CHAR(255)如果字符集的最大字节长度大于3,则列可能会超过768个字节utf8mb4

是否有任何列存储在页外,取决于页面大小和行的总大小。当行太长时, InnoDB选择离页存储的最长列,直到聚簇索引记录适合 B树页面。 TEXT并且 BLOB小于或等于40个字节的列总是在线存储。

DYNAMIC行格式保持存储在它是否适合的索引节点整个行的效率(如做的 COMPACTREDUNDANT 格式),但是DYNAMIC行格式避免填充B-树节点具有大量长列的数据字节的问题。DYNAMIC格式基于这样的想法,即如果长数据值的一部分存储在页外,通常最有效的方法是将所有的值存储在页外。使用DYNAMIC格式,较短的列可能会保留在B-tree节点中,从而最大限度地减少任何给定行所需的溢出页数。

COMPRESSED行格式使用类似的内部细节关闭页存储为DYNAMIC行格式,从表和索引数据的附加存储和性能的考虑被压缩,并使用较小的页大小。使用COMPRESSED行格式,该 KEY_BLOCK_SIZE选项控制聚集索引中存储了多少列数据,以及溢出页面上放置了多少数据。有关COMPRESSED行格式的完整详细信息 ,请参见 第14.9节“InnoDB表和页面压缩”

Both DYNAMIC and COMPRESSED row formats support index key prefixes up to 3072 bytes. This feature is controlled by the innodb_large_prefix configuration option, which is enabled by default. See the innodb_large_prefix option description for more information.

使用COMPRESSED行格式的表格可以在每个文件表格空间或一般表格 空间中 创建系统表空间不支持 COMPRESSED行格式。要将COMPRESSED存储 在每个文件表的表空间中,innodb_file_per_table 必须启用并且 innodb_file_format必须设置为 Barracudainnodb_file_per_tableinnodb_file_format配置选项并不适用于一般的表空间。一般的表空间支持所有的行格式,但需要注意的是,由于物理页面大小不同,压缩和未压缩的表不能共存于相同的常规表空间中。有关常规表空间的更多信息,请参阅 第14.7.9节“InnoDB常规表空间”

DYNAMIC表可以存储在每个表的文件表空间,常规表空间和系统表空间中。要将DYNAMIC存储在系统表空间中,必须使用TABLESPACE [=] innodb_system 带有CREATE TABLE表选项ALTER TABLEinnodb_file_per_tableinnodb_file_format配置选项并不适用于一般的表空间,也没有使用时,它们是适用TABLESPACE [=] innodb_system表选项存储 DYNAMIC在系统表空间表。

您可以DYNAMIC通过禁用innodb_file_per_table和使用常规CREATE TABLEALTER TABLE语句添加到系统表空间 innodb_file_format设置被忽略。一个DYNAMIC表始终使用 Barracuda的文件格式。

DYNAMICCOMPRESSED行格式是变化COMPACT排格式,因此处理CHAR 存储在相同的方式COMPACT行格式。有关更多信息,请参见 第14.8.1.2节“InnoDB表的物理行结构”

14.11.4紧凑和冗余行格式

为数据库文件InnoDB使用未命名文件格式(现称为Antelope)的 早期版本用这种文件格式,表格用ROW_FORMAT=COMPACT定义 ROW_FORMAT=REDUNDANT使用这些行格式, 可以在B-tree节点内的索引记录中InnoDB存储最多768个字节的可变长度列(VARCHAR,, VARBINARYBLOBTEXT类型),其余部分存储在溢出页面中。 还将长度大于或等于768字节的固定长度字段编码为可变长度字段,这些字段可以存储在页外。例如,a InnoDBCHAR(255)如果字符集的最大字节长度大于3,则字段可能会超过768个字节utf8mb4

使用Antelope文件格式时,如果列的值为768字节或更少,则不需要溢出页面,并且可能会导致I / O节省一些,因为该值位于B树节点中。这适用于相对较短的BLOBs,但可能导致B树节点填充数据而不是关键值,从而降低其效率。具有许多BLOB列的表可能会导致B-tree节点变得数据太满,并且包含的​​行太少,这使得整个索引效率低于行较短或列值存储在页外。

有关使用REDUNDANTCOMPACT 行格式的表的物理行结构的信息,请参见第14.8.1.2节“InnoDB表的物理行结构”

14.12 InnoDB磁盘I / O和文件空间管理

作为DBA,您必须管理磁盘I / O以防止I / O子系统变得饱和,并管理磁盘空间以避免填满存储设备。ACID设计模型需要一定量的I / O可能似乎是多余的,但有助于确保数据的可靠性。在这些约束条件下, InnoDB尝试优化数据库工作和磁盘文件的组织以最小化磁盘I / O的数量。有时候,I / O被推迟到数据库不忙,或者直到所有的事情都需要进入一致的状态,比如在快速关闭后的数据库重启过程中

本节讨论使用默认类型的MySQL表(也称为InnoDB表)来处理I / O和磁盘空间的主要注意事项

  • 控制用于提高查询性能的后台I / O数量。

  • 启用或禁用以额外I / O为代价提供额外耐用性的功能。

  • 将表组织成许多小文件,几个大文件或两者的组合。

  • 将重做日志文件的大小与日志文件变满时发生的I / O活动进行平衡。

  • 如何重新组织表以获得最佳查询性能。

14.12.1 InnoDB磁盘I / O

InnoDB尽可能使用异步磁盘I / O,通过创建大量线程来处理I / O操作,同时在I / O仍在进行时允许其他数据库操作继续。在Linux和Windows平台上,InnoDB使用可用的操作系统和库函数来执行本地异步I / O。在其他平台上,InnoDB仍然使用I / O线程,但这些线程可能实际上等待I / O请求完成; 这种技术被称为模拟 异步I / O。

预读

如果InnoDB可以确定很快就会需要数据的可能性很高,则它会执行预读操作以将该数据带入缓冲池,以使其在内存中可用。对连续数据做出一些较大的读取请求可能比创建几个小的扩展请求更有效。有两个预读启发式InnoDB

  • 在顺序预读中,如果InnoDB 通知表空间中的段的访问模式是连续的,则它预先向I / O系统发送一批数据库页的读取。

  • 在随机预读中,如果InnoDB通知表空间中的某个区域似乎处于完全读入缓冲池的过程中,则会将剩余的读数发布到I / O系统。

有关配置预读试探法的信息,请参见 第14.6.3.5节“配置InnoDB缓冲池预取(预读)”

双写缓冲区

InnoDB使用一种新颖的文件刷新技术,涉及称为双写缓冲区的结构 ,在大多数情况下(innodb_doublewrite=ON,默认启用它增加了崩溃或停电后恢复的安全性,并通过减少fsync()操作需求来提高大多数Unix系统的性能

在将页面InnoDB 写入数据文件之前,首先将它们写入连续的表空间区域,称为doublewrite缓冲区。只有在写入和刷新到双InnoDB缓冲区之后,才会将页面写入数据文件中的正确位置。如果操作系统,存储子系统或 mysqld进程在页面写入过程中崩溃(导致页面被破坏 ),InnoDB稍后可以在恢复过程中从双写缓冲区中找到页面的正确副本。

如果系统表空间文件(ibdata文件)位于支持原子写入的Fusion-io设备上,则会自动禁用双写缓冲,并将Fusion-io原子写入用于所有数据文件。由于双写缓冲区设置是全局性的,所以对于驻留在非Fusion-io硬件上的数据文件,也会禁用双写缓冲。此功能仅在Fusion-io硬件上受支持,并且仅适用于Linux上的Fusion-io NVMFS。要充分利用此功能,建议使用innodb_flush_method设置 O_DIRECT

14.12.2文件空间管理

您在配置文件中使用innodb_data_file_path 配置选项在InnoDB 系统表空间中定义的数据文件 这些文件被逻辑连接起来以形成系统表空间。没有使用条纹。您无法定义您的表分配到系统表空间的哪个位置。在新创建的系统表空间中,InnoDB从第一个数据文件开始分配空间。

为避免在系统表空间中存储所有表和索引时出现的问题,可以启用 innodb_file_per_table 配置选项(默认值),该选项将每个新创建的表存储在单独的表空间文件(带扩展名 .ibd)中。对于以这种方式存储的表,磁盘文件中的碎片较少,并且在截断表时,该空间将返回到操作系统,而不是仍然由InnoDB在系统表空间中保留。有关更多信息,请参见 第14.7.4节“InnoDB文件 - 每个表空间”

您也可以将表存储在 一般的表空间中常规表空间是使用CREATE TABLESPACE 语法创建的共享表空间它们可以在MySQL数据目录之外创建,能够保存多个表格,并支持所有行格式的表格。有关更多信息,请参见 第14.7.9节“InnoDB常规表空间”

页面,范围,段和表空间

每个表空间由数据库页面组成 MySQL实例中的每个表空间都具有相同的页面大小默认情况下,所有表空间的页面大小为16KB; 通过innodb_page_size在创建MySQL实例时指定选项,可以将页面大小减小到8KB或4KB 您还可以将页面大小增加到32KB或64KB。有关更多信息,请参阅 innodb_page_size文档。

页被分成 区段大小为1MB用于尺寸的页面到16KB(64次连续的16KB的页面,或128 8KB页或256 4KB页)。对于32KB的页面大小,区段大小为2MB。对于64KB的页面大小,区段大小为4MB。文件表空间内被称为 InnoDB(这些段与回滚段不同 ,后者实际上包含许多表空间段。)

当一个分段在表空间内增长时,一次 InnoDB为其分配前32个页面。之后,InnoDB开始为该细分受众群分配整个范围。InnoDB 可以一次将最多4个区段添加到大型区段,以确保数据的良好顺序性。

两个分段分配给每个索引 InnoDB一个用于 B树的非叶节点,另一个用于叶节点。在磁盘上保持叶节点连续可以实现更好的顺序I / O操作,因为这些叶节点包含实际的表数据。

表空间中的某些页面包含其他页面的位图,因此InnoDB表空间中的一些扩展区不能作为整体分配给段,而只能作为单独页面分配。

当您通过发出SHOW TABLE STATUS语句要求表空间中的可用空间时,请 InnoDB报告表空间中的空闲空间。InnoDB总是保留一些清理和其他内部目的的程度; 这些保留的扩展区不包含在可用空间中。

从表中删除数据时,InnoDB 合同对应的B树索引。释放空间是否可用于其他用户取决于删除模式是否将个别页面或扩展区释放到表空间。删除表或删除其中的所有行可确保将空间释放给其他用户,但请记住,删除的行仅通过清除操作进行物理删除,删除 操作在事务回滚或一致读取不再需要它们一段时间后自动发生。(请参见 第14.3节“InnoDB多版本控制”。)

页面如何与表格行相关联

对于4KB,8KB,16KB和32KB innodb_page_size设置,最大行长度略小于数据库页面的一半 例如,对于默认的16KB InnoDB页面大小,最大行长度略小于8KB 对于64KB的页面,最大行长度略小于16KB。

如果一行没有超过最大行长度,则它全部存储在本地页面中。如果一行超过最大行长度,则将可变长度列选择用于外部页外存储,直到该行适合最大行长度限制。可变长度列的外部页外存储按行格式不同:

  • 精简和冗余行格式

    当为外部页外存储选择可变长度的列时,InnoDB将本地前768个字节存储在该行中,其余部分存储在溢出页面中。每个这样的列都有自己的溢出页面列表。768字节的前缀伴随着一个20字节的值,该值存储列的真实长度并指向溢出列表,其中存储剩余的值。请参见 第14.11.4节“精简和冗余行格式”

  • DYNAMIC和COMPRESSED行格式

    当为外部页外存储选择可变长度列时,InnoDB将20字节指针本地存储在行中,其余部分存储在溢出页中。请参见第14.11.3节“动态和压缩行格式”

LONGBLOB并且 LONGTEXT列必须小于4GB,并且总行长度(包括 BLOBTEXT列)必须小于4GB。

14.12.3 InnoDB检查点

使你的日志文件非常大时可以减少磁盘I / O的 检查点将日志文件的总大小设置为与缓冲池一样大或者甚至更大是很有意义的。尽管在过去,大型日志文件可能会让崩溃恢复花费过多时间,从MySQL 5.5开始,崩溃恢复的性能增强使得可以在崩溃后快速启动时使用大型日志文件。(严格地说,这个性能改进适用于InnoDB Plugin 1.0.7及更高版本的MySQL 5.1,MySQL 5.5中这种改进在默认InnoDB存储引擎中可用。)

检查点处理如何工作

InnoDB实现称为模糊检查点检查点机制小批量从缓冲池中刷新修改后的数据库页面。无需在单个批处理中刷新缓冲池,这会在检查点过程中中断用户SQL语句的处理。 InnoDB

崩溃恢复期间InnoDB查找写入日志文件的检查点标签。它知道标签之前对数据库的所有修改都存在于数据库的磁盘映像中。然后InnoDB从检查点向前扫描日志文件,将已记录的修改应用到数据库。

14.12.4对表进行碎片整理

随机插入或从辅助索引中删除可能导致索引变成碎片。碎片意味着磁盘上索引页的物理顺序不接近页面记录的索引排序,或者分配给索引的64页块中有很多未使用的页面。

碎片化的一个症状是,一张桌子比应该需要更多的空间究竟是多少,难以确定。所有InnoDB数据和索引都存储在B树中,其填充因子可能在50%到100%之间变化。碎片的另一个症状是像这样的表扫描需要比应该更多的时间

SELECT COUNT(*)FROM t WHERE non_indexed_column<> 12345;

前面的查询要求MySQL执行全表扫描,这是大型表最慢的查询类型。

为了加速索引扫描,你可以定期执行一个 ALTER TABLE 操作,这会导致MySQL重建表:

ALTER TABLE tbl_nameENGINE = INNODB

您也可以使用 执行重建表 alter操作。 ALTER TABLE tbl_name FORCE

双方使用 在线DDL有关更多信息,请参见第14.13.1节“在线DDL概述”ALTER TABLE tbl_name ENGINE=INNODBALTER TABLE tbl_name FORCE

执行碎片整理操作的另一种方法是使用 mysqldump将表转储到文本文件,删除表并从转储文件重新加载。

如果插入到索引中始终是升序并且只从最后删除记录,则InnoDB 文件空间管理算法可确保索引中的碎片不会发生。

14.12.5使用TRUNCATE TABLE回收磁盘空间

当回收操作系统的磁盘空间 截断InnoDB表,该表必须存放在自己的的.ibd文件。要将表存储在其自己的.ibd 文件中,innodb_file_per_table必须在创建表时启用。另外,在被截断的表和其他表之间不能有 外键约束,否则 TRUNCATE TABLE操作失败。但是,同一个表中两列之间的外键约束是允许的。

当表被截断时,它将被删除并在新.ibd文件中重新创建 ,并且释放的空间将返回到操作系统。这与截断InnoDB存储在 InnoDB 系统表空间 (表创建时的表innodb_file_per_table=OFF)和存储在共享 通用表空间中的表的对比 ,其中只能InnoDB在截断表后使用释放的空间。

截断表和向操作系统返回磁盘空间的能力也意味着 物理备份可以更小。截断存储在系统表空间(当创建表时 innodb_file_per_table=OFF)或在常规表空间中的表时,会在表空间中留下未使用空间的块。

14.13 InnoDB和Online DDL

InnoDB 在线DDL功能允许就地改建表或同时 DML,或两者兼而有之。此功能的好处包括:

  • 在繁忙的生产环境中改进响应能力和可用性,使得桌子在几分钟或几小时内不可用。

  • 使用子句DDL操作期间调整性能和并发之间的平衡的能力LOCK

    • LOCK=EXCLUSIVE 完全禁止访问表格。

    • LOCK=SHARED 允许查询但不包含DML。

    • LOCK=NONE 允许对表进行完整的查询和DML访问。

    • LOCK=DEFAULT或者LOCK根据DDL操作的类型省略该 子句允许尽可能多的并发性。

  • 避免与复制表格和重建二级索引相关的磁盘空间使用情况和I / O开销。

14.13.1在线DDL概述

在线DDL功能增强了以前需要在表格上进行表格复制或阻止DML操作的许多DDL操作,或两者兼而有之。表14.10“DDL操作的联机状态”显示了联机DDL功能如何应用于每个DDL语句。

除大多数ALTER TABLE分区子句外,分区InnoDB表的联机DDL操作遵循适用于常规InnoDB的相同规则有关更多信息,请参见第14.13.7节“分区表的联机DDL”

一些因素会影响在线DDL操作的性能,空间使用情况和语义。有关更多信息,请参见 第14.13.8节“在线DDL限制”

  • 就地?列显示哪些操作允许该ALGORITHM=INPLACE子句。

  • 重建表?列显示哪些操作重建表。对于使用该INPLACE算法的操作, 表格已重建。对于不支持该 INPLACE算法的操作,表格复制方法用于重建表格。

  • 许可证并发DML?列显示哪些操作完全在线执行。您可以指定 LOCK=NONE在DDL操作期间声明允许并发DML。如果可能,MySQL会自动允许并发DML。

    所有在线DDL操作都允许并发查询。您可以指定LOCK=SHARED在DDL操作期间声明允许并发查询。MySQL尽可能自动允许并发查询。

  • 备注栏提供了额外的信息,并说明有关的异常和依赖关系是/否等栏目的值。星号表示异常或依赖关系。

表14.10 DDL操作的联机状态

手术 到位? 重建表格? 允许并发DML? 只修改元数据? 笔记
CREATE INDEXADD INDEX 是* 没有* 没有 限制适用于FULLTEXT指数; 见下一行。
ADD FULLTEXT INDEX 是* 没有* 没有 没有 FULLTEXT如果没有用户定义的FTS_DOC_ID 列,添加第一个索引将重建表后续FULLTEXT索引可能会添加到同一个表上而不重建表。
ADD SPATIAL INDEX 没有 没有 没有
RENAME INDEX 没有 只修改表格元数据。
DROP INDEX 没有 只修改表格元数据。
OPTIMIZE TABLE 是* 没有 具有FULLTEXT索引的表格不支持就地操作
设置列的默认值 没有 只修改表格元数据。
更改自动增量 没有 没有* 修改存储在内存中的值,而不是数据文件。
添加外键约束 是* 没有 INPLACE算法在foreign_key_checks禁用时受支持 否则,只COPY 支持算法。
删除外键约束 没有 foreign_key_checks 可以启用或禁用。
重命名列 是* 没有 是* 要允许并发DML,请保持相同的数据类型并只更改列名称。ALGORITHM=INPLACE不支持重命名 生成的列
添加列 是* 是* 是* 没有 添加自动增量时,不允许并发DML 数据被大量重组,使其成为一项昂贵的操作。ALGORITHM=INPLACE支持添加 虚拟生成列,但不支持添加 存储的生成列添加虚拟生成的列不需要重建表。
删除列 是* 没有 数据被大量重组,使其成为一项昂贵的操作。 ALGORITHM=INPLACE支持删除生成的列。删除 虚拟生成的列不需要重建表。
对列重新排序 没有 数据被大量重组,使其成为一项昂贵的操作。
更改ROW_FORMAT属性 没有 数据被大量重组,使其成为一项昂贵的操作。
更改KEY_BLOCK_SIZE属性 没有 数据被大量重组,使其成为一项昂贵的操作。
制作专栏 NULL 是* 没有 重建表格。数据被大量重组,使其成为一项昂贵的操作。
制作专栏 NOT NULL 是* 没有 重建表格。STRICT_ALL_TABLES或者 STRICT_TRANS_TABLES SQL_MODE是操作成功所必需的。如果该列包含NULL值,则操作失败。服务器禁止更改可能导致引用完整性丢失的外键列。请参见第13.1.8节“ALTER TABLE语法”数据被大量重组,使其成为一项昂贵的操作。
更改列数据类型 没有* 没有 没有 VARCHAR大小可能会增加使用在线ALTER TABLE请参阅 修改列属性以获取更多信息。
添加主键 是* 是* 没有 重建表格。数据被大量重组,使其成为一项昂贵的操作。 ALGORITHM=INPLACE在某些条件下,如果需要将列转换为列,则不允许使用 NOT NULL
删除主键并添加另一个 没有 数据被大量重组,使其成为一项昂贵的操作。
删除主键 没有 没有 没有 ALGORITHM=COPY支持在相同ALTER TABLE语句中添加主键而不添加新键
转换字符集 没有 是* 没有 没有 如果新字符编码不同,则重建表格。
指定字符集 没有 是* 没有 没有 如果新字符编码不同,则重建表格。
重建FORCE选项 是* 没有 用途ALGORITHM=INPLACEALGORITHM=INPLACE不支持带FULLTEXT索引的
null使用重建ALTER TABLE ... ENGINE=INNODB 是* 没有 用途ALGORITHM=INPLACEALGORITHM=INPLACE不支持带FULLTEXT索引的
STATS_PERSISTENTSTATS_AUTO_RECALCSTATS_SAMPLE_PAGES 执着统计选项 没有 只修改表格元数据。
ALTER TABLE … ENCRYPTION 没有 没有
放下一STORED 是* 没有 重建表格。
修改STORED列顺序 是* 没有 重建表格。
添加一STORED 是* 没有 重建表格。
放下一VIRTUAL 没有
修改VIRTUAL列顺序 没有
添加一VIRTUAL 没有

以下各节提供了各种在线DDL操作的基本语法和使用说明。

添加或删除二级索引

  • 添加辅助索引

    CREATE INDEX nameON tablecol_list);
    
    ALTER TABLE tableADD INDEX namecol_list);
    
  • 删除辅助索引:

    DROP INDEX nameON table;
    
    ALTER TABLE tableDROP INDEX name;
    

虽然不需要语法变化 CREATE INDEXDROP INDEX命令,一些因素会影响性能,空间使用,而这个操作的语义(见第14.13.8,“在线DDL限制”)。

InnoDB上创建和删除二级索引将 跳过表复制行为。

在创建或删除索引时,该表仍可用于读取和写入操作。CREATE INDEXDROP INDEX正在访问表中的所有交易完成后语句只完成,因此该指数的初始状态反映最近的表的内容。此前,修改表,同时索引被创建或通常下降导致了 僵局是取消了 INSERTUPDATE或者 DELETE声明在桌子上。

在线DDL支持添加二级索引意味着通常可以通过创建没有任何二级索引的表来加速创建和加载表和相关索引的整个过程,然后在加载数据后添加二级索引。

修改列属性

  • 修改列的默认值:

    ALTER TABLE tblALTER COLUMN colSET DEFAULT literal;
    
    ALTER TABLE tblALTER COLUMN colDROP DEFAULT;
    

    列的默认值存储在表格.frm文件中,而不是InnoDB 数据字典

  • 更改列的 自动增量 值:

    ALTER TABLE tableAUTO_INCREMENT = next_value;
    

    特别是在使用复制或分片的分布式系统中,有时您会将表的自动增加计数器重置为特定值。插入到表中的下一行将为其自动增量列使用指定的值。您也可以在数据仓库环境中使用该技术,在该环境中定期清空所有表并重新加载它们,然后可以从1重新开始自动递增序列。

  • 重命名一列:

    ALTER TABLE tblCHANGE ;
    old_col_name new_col_name datatype

    如果保持相同的数据类型和[NOT] NULL属性,只更改列名称,则可始终在线执行此操作。

    您还可以重命名属于外键约束的一列。外键定义自动更新为使用新的列名称。重命名参与外键的列仅适用于in-place模式ALTER TABLE如果使用该ALGORITHM=COPY子句或其他一些条件导致该命令ALGORITHM=COPY在幕后使用 ,则该 ALTER TABLE语句失败。

  • VARCHAR使用就地ALTER TABLE语句 扩展大小

    ALTER TABLE t1 ALGORITHM = INPLACE,CHANGE COLUMN c1 c1 VARCHAR(255);
    

    VARCHAR 所需的长度字节数 必须保持不变。对于VARCHAR0到255的值,需要一个长度字节来对该值进行编码。对于 VARCHAR256字节或更多的值,需要两个长度字节。因此,in-place ALTER TABLE只支持VARCHAR从0到255个字节的增加VARCHAR大小从等于或大于256个字节的值增加 大小。就地 ALTER TABLE不支持增加VARCHAR大小从小于256字节到等于或大于256字节的值。在这种情况下,所需的长度字节数将从1更改为2,这只能由表副本(ALGORITHM=COPY)支持。例如,试图VARCHAR使用in-place ALTER TABLE列大小从255 更改为256 会返回错误:

    ALTER TABLE t1 ALGORITHM = INPLACE,CHANGE COLUMN c1 c1 VARCHAR(256);
    错误0A000:ALGORITHM = INPLACE不受支持。原因:无法更改
    列类型INPLACE。尝试ALGORITHM = COPY。
    

    不支持VARCHAR使用in-place 减小大小ALTER TABLE减小VARCHAR 大小需要一个表副本(ALGORITHM=COPY)。

添加或删除外键

  • 添加或删除a 外键约束

    ALTER TABLE tbl1ADD CONSTRAINT fk_nameFOREIGN KEY indexcol1
      参考文献tbl2col2referential_actions ;
    
    ALTER TABLE tblDROP FOREIGN KEYfk_name ;
    

    通过foreign_key_checks启用或禁用选项,可以在线执行删除外键 在线创建外键需要 foreign_key_checks被禁用。

    如果您不知道特定表上外键约束的名称,请发出以下语句并在中找到约束名称 CONSTRAINT每个外键子句中

    SHOW CREATE TABLE table \ G
    

    或者,查询 INFORMATION_SCHEMA.TABLE_CONSTRAINTS 表并使用CONSTRAINT_NAMECONSTRAINT_TYPE列标识外键名称。

    您也可以在一个语句中删除一个外键及其关联的索引:

    ALTER TABLE tableDROP FOREIGN KEY constraint,DROP INDEX index;
    

如果外键已经存在于被修改的表中(即它是一个包含 子句子表FOREIGN KEY ... REFERENCE),则对在线DDL操作(即使不是直接涉及外键列的操作)也会有其他限制:

  • 一个ALTER TABLE子表上可以等待其他事务提交时,如果更改了父表通过引起子表的相关变化ON UPDATEON DELETE使用子句 CASCADESET NULL 参数。

  • 以同样的方式,如果表是 父表的外键关系,即使它不包含任何 FOREIGN KEY条款,它可以等待 ALTER TABLE完成如果一个 INSERTUPDATEDELETE语句会引起 ON UPDATEON DELETE 子表的行动。

维护CREATE TABLE语句

随着数据库模式随着新列,数据类型,约束,索引等的发展而变化,请CREATE TABLE使用最新的表定义使语句保持 最新。即使在线DDL的性能有所提高,但在开始时创建稳定的数据库结构效率更高,而不是创建模式的一部分,然后再发布ALTER TABLE语句。

此准则的主要例外是对 具有大量行的表的二级索引通常,使用除辅助索引外的所有详细信息创建表,加载数据,然后创建辅助索引是最有效的。如果您知道初始数据是干净的并且在加载过程中不需要一致性检查,则可以使用与外键相同的技术 (首先加载数据,然后设置外键)。

无论序列CREATE TABLECREATE INDEXALTER TABLE,和类似表述走进了把一个表一起,你可以捕获通过发出声明,以重建表的当前形式所需的SQL (大写 为整齐的格式要求)。此输出显示子句,如数字精度,以及有时会添加到幕后,在克隆新系统上的表或设置具有相同类型的外键列时,可能不需要这些子句SHOW CREATE TABLE table\G\GNOT NULLCHARACTER SET

14.13.2在线DDL性能,并发性和空间要求

在线DDL改进了MySQL操作的几个方面,例如性能,并发性,可用性和可伸缩性:

  • 因为 在DDL进行时,表上的查询和DML操作可以继续进行,所以访问该表的应用程序响应性更强。减少 锁定并等待整个MySQL服务器中的其他资源,从而实现更高的可伸缩性,即使对于不涉及表格更改的操作也是如此。

  • 对于就地操作,通过避免磁盘I / O和CPU周期来重建表,可以最大限度地减少数据库的总体负载,并在DDL操作期间保持良好的性能和高吞吐量。

  • 对于就地操作,因为与复制所有数据相比,读入缓冲池的数据量更少,所以 您可以避免从内存中清除频繁访问的数据,这些数据以前可能会导致DDL操作后临时性能下降。

如果在线操作需要临时排序文件,则 InnoDB默认在临时文件目录中创建它们,而不是包含原始表格的目录。如果此目录不足以容纳此类文件,则可能需要将tmpdir 系统变量设置为不同的目录。或者,您可以使用配置选项InnoDB在线ALTER TABLE操作 定义一个单独的临时目录 innodb_tmpdir有关更多信息,请参阅 联机DDL操作的空间要求以及 第B.5.3.5节“MySQL存储临时文件的位置”

锁定在线DDL的选项

虽然InnoDB表正在通过DDL操作进行更改,但根据该操作的内部工作原理和语句子句,该表可能锁定也可能不 锁定默认情况下,在DDL操作期间,MySQL使用尽可能少的锁定; 您可以指定子句,以使锁定比通常情况下更具限制性(从而限制并发DML或DML和查询),或者确保某个操作允许某种预期锁定程度。如果子句指定的锁定级别不适用于该特定种类的DDL操作,如 orLOCKALTER TABLELOCKLOCK=SHAREDLOCK=NONE 在创建或删除主键时,该子句像断言一样工作,导致语句失败并出现错误。以下列表显示了LOCK从最宽容到最严格条款的不同可能性

  • 对于DDL操作LOCK=NONE,允许查询和并发DML。ALTER TABLE如果无法使用所请求的锁定类型执行DDL操作,则此子句会导致失败,因此请指定LOCK=NONE保留表的完整可用性至关重要,如果无法取消DDL,则可以取消该DDL。例如,您可以在涉及客户注册或购买的表中使用DDL中的此子句,以避免错误地发出昂贵的ALTER TABLE声明而使这些表不可用

  • 对于DDL操作LOCK=SHARED,对表的任何写入(即DML操作)都会被阻止,但可以读取表中的数据。ALTER TABLE如果不能使用所请求的锁定类型执行DDL操作,则此子句会导致 失败,因此请指定LOCK=SHARED保留可用于查询的表是否至关重要,如果无法取消DDL,则可以取消该DDL。例如,您可以在DDL中将此子句用于数据仓库中的表,可以将数据加载操作延迟到DDL完成,但查询不能长时间延迟。

  • 对于带有LOCK=DEFAULTLOCK省略子句的DDL操作,MySQL使用可用于该类操作的最低级别的锁定,允许并发查询,DML或两者都尽可能。这是在进行预先规划的,预先测试过的变更时使用的设置,根据该表的工作负载,您知道这些变更不会导致任何可用性问题。

  • 对于DDL操作LOCK=EXCLUSIVE,查询和DML操作都被阻止。ALTER TABLE如果使用所请求的类型的锁定无法执行DDL操作,则此子句会导致失败,因此请指定 LOCK=EXCLUSIVE主要关注点是否在尽可能最短的时间内完成DDL,并且可以让应用程序在尝试访问时等待桌子。LOCK=EXCLUSIVE 如果服务器应该处于空闲状态,也可以使用,以避免意外访问表。

在大多数情况下,表上的联机DDL操作会等待当前正在执行的正在访问表的事务 提交回滚,因为在准备DDL语句时,它需要在短时间内独占访问表。同样,在线DDL操作在完成之前需要短时间独占访问表。因此,联机DDL语句还等待在DDL正在执行时启动的事务在完成之前提交或回滚。因此,在执行插入,更新,删除或者长时间运行的事务的情况下SELECT ... FOR UPDATE对表进行操作时,可能会使在线DDL操作超时等待对表的独占访问。

在表中的联机DDL操作不等待当前正在执行的事务完成的情况下,当表处于外键关系并且事务在外键关系中的另一个表上显式运行时,可能会发生这种情况。在这种情况下,事务在它正在更新的表上保存一个独占的元数据锁,但仅InnoDB在另一个表上保存共享 表锁(用于外键检查)。共享 InnoDB表锁定允许联机DDL操作继续,但在专用阶段阻止提交阶段的操作InnoDB表锁是必需的。这种情况会导致死锁,因为其他事务等待在线DDL操作提交。(请参阅错误#48652和错误#77390)

因为记录并发DML操作所做的更改需要一些处理工作,所以在最后应用这些更改时,联机DDL操作可能比阻止其他会话访问表的旧式机制花费更长的时间。原始性能的降低与使用该表的应用程序的更好的响应性相平衡。在评估改变表格结构的理想技术时,根据诸如网页加载时间等因素考虑最终用户对性能的感知。

新创建的InnoDB二级索引只包含执行CREATE INDEXALTER TABLE语句执行时表中的提交数据 它不包含任何未提交的值,旧版本的值或标记为删除但尚未从旧索引移除的值。

性能的就地与表复制DDL操作

在线DDL操作的原始性能很大程度上取决于操作是在原地执行还是需要复制和重建整个表格。请参阅 表14.10,“DDL操作的联机状态”,查看可以在何处执行的操作以及避免执行表复制操作的任何要求。

来自原地DDL的性能提速适用于二级索引上的操作,而不适用于主键索引。InnoDB表的行存储在 基于主键组织聚集索引中,形成一些数据库系统称为 索引组织表 ”的内容由于表结构与主键密切相关,重新定义主键仍然需要复制数据。

当主键上的操作使用时 ALGORITHM=INPLACE,即使数据仍被复制,它比使用效率更高, ALGORITHM=COPY因为:

  • 不需要撤消日志记录或关联的重做日志记录 ALGORITHM=INPLACE这些操作会为使用的DDL语句增加开销 ALGORITHM=COPY

  • 辅助索引条目是预先排序的,因此可以按顺序加载。

  • 不使用更改缓冲区,因为在辅助索引中没有随机访问插入。

为了判断在线DDL操作的相对性能,可以InnoDB使用当前版本和早期版本的MySQL 在大型上运行这些操作您还可以在最新的MySQL版本下运行所有​​性能测试,通过设置系统变量来模拟之前结果 ”的 DDL行为 old_alter_tableset old_alter_table=1在会议中发表声明,并衡量DDL表现以记录之前 ”的数字。然后 set old_alter_table=0重新启用更新,更快的行为,并再次运行DDL操作以记录 之后数字。

有关DDL操作是在原地进行更改还是执行表副本的基本概念,请查看命令完成后显示受影响值。例如,以下是执行不同类型的DDL操作后可能会看到的行:

  • 更改列的默认值(超快速,根本不影响表数据):

    查询OK,0行受影响(0.07秒)
    
  • 添加一个索引(需要时间,但0 rows affected显示表格未被复制):

    查询OK,0行受影响(21.42秒)
    
  • 更改列的数据类型(需要大量时间,并且需要重新构建表的所有行):

    查询OK,1671168行受影响(1分35.54秒)
    
    注意

    更改列的数据类型需要重新VARCHAR构建表的所​​有行,但可以使用联机更改 大小ALTER TABLE请参阅 修改列属性以获取更多信息。

例如,在大型表上运行DDL操作之前,可以按如下方式检查操作是快速还是慢速:

  1. 克隆表结构。

  2. 用少量数据填充克隆表。

  3. 在克隆的表上运行DDL操作。

  4. 检查rows affected值是否为零。非零值意味着操作需要重建整个表格,这可能需要特殊的计划。例如,您可以在计划停机时间段内或每次在一台复制从属服务器上执行DDL操作。

对于在MySQL处理的减少更深入的了解,检查performance_schemaINFORMATION_SCHEMA相关的表格 InnoDB前,DDL操作后,看到许多物理读,写,内存分配,等等。

在线DDL操作的空间要求

在线DDL操作具有以下空间要求:

  • 临时日志文件的空间

    对于正在创建的每个索引或正在更改的表,都有一个这样的日志文件。该日志文件存储在DDL操作期间插入,更新或删除的表中的数据。当需要时,临时日志文件将被扩展innodb_sort_buffer_size,直到达到最大值 innodb_online_alter_log_max_size如果临时日志文件超过了大小上限,则 ALTER TABLE操作失败,所有未提交的并发DML操作都会回滚。因此,此选项的较大值允许在联机DDL操作期间发生更多DML,但是也可以延长DDL操作结束时的时间间隔,以便锁定表以应用日志中的数据。

    如果该操作需要很长时间,并且DML并发地修改了该表,那么临时联机日志的大小超过了innodb_online_alter_log_max_size 配置选项的值 ,则联机DDL操作将失败并显示 DB_ONLINE_LOG_TOO_BIG错误。

  • 临时排序文件的空间

    重建表的在线DDL操作将临时排序文件写入MySQL临时目录($TMPDIR在Unix %TEMP%上,Windows上或由--tmpdir 配置变量)。每个临时排序文件都足够大,可以容纳为新的辅助索引定义的所有列以及作为聚簇索引主键一部分的列,并且每当临时排序文件合并到最终表或索引时就会被删除。这些操作可能需要临时空间等于表中数据量加上索引。如果操作使用数据目录(datadir)所在文件系统上的所有可用磁盘空间,则重建表的联机DDL操作可能会导致错误

    从MySQL 5.7.11开始,您可以使用 innodb_tmpdir配置选项为在线DDL操作定义一个单独的临时目录。innodb_tmpdir引入选项是为了避免在ALTER TABLE重建表的联机操作期间创建的大型临时排序文件导致临时目录溢出

  • 中间表文件的空间

    重建表的一些联机DDL操作会在与原始表相同的目录中创建临时中间表文件,而不是重新创建表。中间表文件可能需要的空间等于原始表的大小。第14.13.1节“在线DDL概述”中记录了重建表的操作

14.13.3联机DDL SQL语法

通常,在使用表格语句 ,您无需执行任何特殊的操作即可启用 联机DDL请参阅 表14.10,“DDL操作的联机状态”,了解可以在原地执行的DDL操作类型,允许并发DML或两者。一些变化需要配置设置或子句的特定组合ALTER TABLEInnoDBALTER TABLE

您可以通过控制特定的在线DDL操作的各个方面LOCKALGORITHM该子句 ALTER TABLE声明。这些条款出现在声明的最后,并以逗号分隔列表和列规范。LOCK 子句对于微调并发访问表的程度很有用。ALGORITHM子句主要用于性能比较,以及在遇到与现有DDL代码有关的任何问题时作为旧表复制行为的回退。例如:

  • 为避免意外使表不可用于读取,写入或两者,请在ALTER TABLE语句中指定一个子句 LOCK=NONE如同时 允许读取和写入)或 LOCK=SHARED(允许读取)。如果请求的并发级别不可用,该操作会立即停止。

  • 要比较性能,请使用ALGORITHM=INPLACE另一个 语句运行一个语句 ALGORITHM=COPY,作为设置old_alter_table 配置选项的替代方法

  • 为避免将服务器与ALTER TABLE复制表操作捆绑在一起 ,请包括 ALGORITHM=INPLACE如果语句不能使用就地机制,该语句立即停止。请参阅 表14.10,“DDL操作的联机状态”,以获取可以或不可以在原地执行的DDL操作列表。

有关该子句的更多详细信息 请参见第14.13.2节“在线DDL性能,并发性和空间要求”LOCK

14.13.4使用在线DDL简化DDL语句

在引入在线DDL之前,将许多DDL操作合并为一个ALTER TABLE 语句是很常见的做法因为每个ALTER TABLE 语句都涉及复制和重建表,所以一次对同一个表进行多次更改会更高效,因为这些更改都可以通过对表执行单个重建操作来完成。缺点是涉及DDL操作的SQL代码难以维护并在不同的脚本中重复使用。如果每次具体更改都不相同,则可能需要ALTER TABLE为每个稍有不同的场景构建一个新的复合体

对于可以在原地完成的DDL操作(如 表14.10“DDL操作的联机状态”所示),现在可以将它们分离为单独的ALTER TABLE语句,以便于脚本编写和维护,而不会影响效率。例如,您可能会采取复杂的语句,例如:

ALTER TABLE t1 ADD INDEX i1(c1),ADD UNIQUE INDEX i2(c2),
  更改c4_old_name c4_new_name INTEGER UNSIGNED;

并将其分解成可以独立测试和执行的更简单的部分,例如:

ALTER TABLE t1 ADD INDEX i1(c1);
ALTER TABLE t1 ADD UNIQUE INDEX i2(c2);
ALTER TABLE t1 CHANGE c4_old_name c4_new_name INTEGER UNSIGNED NOT NULL;

您可能仍然使用以下部分的多部分ALTER TABLE语句:

  • 必须以特定顺序执行的操作,例如创建索引后跟使用该索引的外键约束。

  • 所有操作都使用相同的特定LOCK 条款,您希望成功或失败作为一个组。

  • 无法在原地执行的操作,即仍然复制并重建表格的操作。

  • 您指定的操作, ALGORITHM=COPY或者 old_alter_table=1如果需要强制执行表复制行为,以便在特定方案中实现精确的向后兼容。

14.13.5在线DDL实现细节

表格的 每项ALTER TABLE操作 InnoDB都受以下几个方面的控制:

  • 表格的物理表示是否有任何改变,或者它是否完全改变元数据,而不用触摸表格本身。

  • 表中的数据量是否保持不变,增加还是减少。

  • 表数据的更改是涉及聚集索引,二级索引还是两者。

  • 在被修改的表和其他表之间 是否有任何外键关系。根据foreign_key_checks 配置选项是启用还是禁用,机制有所不同

  • 表是否已分区。分区子句 ALTER TABLE变成涉及一个或多个表的低级操作,并且这些操作遵循在线DDL的常规规则。

  • 是否必须复制表格数据,表格是否可以就地重组,或两者的组合。

  • 该表是否包含任何 自动增量 列。

  • 根据基础数据库操作的性质或您在 声明中指定子句,需要 什么程度的锁定LOCKALTER TABLE

在线DDL的错误条件

以下是在线DDL操作失败的主要原因:

  • 如果一个LOCK子句指定了与特定类型的DDL操作不兼容的低度锁定(SHAREDNONE)。

  • 如果在等待在表上获得排它锁时发生超时 ,在DDL操作的初始阶段和最终阶段可能需要暂时需要该

  • 如果tmpdirinnodb_tmpdir文件系统运行的磁盘空间,而MySQL索引的创建过程中,在磁盘上写入临时排序文件。有关更多信息,请参见 第B.5.3.5节“MySQL存储临时文件的位置”

  • 如果ALTER TABLE花费这么长时间,并且DML同时修改表,那么临时在线日志的大小超过了innodb_online_alter_log_max_size 配置选项的值 这种情况会导致 DB_ONLINE_LOG_TOO_BIG错误。

  • 如果并发DML对原始表定义所允许的表进行更改,但不更改新表。当MySQL尝试应用来自并发DML语句的所有更改时,该操作仅在最后才会失败。例如,可以在创建唯一索引时将重复值插入列中,或者可以NULL在创建该列的主键索引值插入 列中。并发DML所做的更改优先,并且ALTER TABLE 操作有效回滚

尽管配置选项 innodb_file_per_tableInnoDB的表示有显着影响,但 无论启用还是禁用该选项,以及该表是物理位于其自己的.ibd文件还是位于系统表空间,所有联机DDL操作都可以很好地工作

InnoDB有两种类型的索引: 表示表中所有数据聚集索引和可选的 二级索引加快查询速度。由于聚簇索引在其B树节点中包含数据值,因此添加或删除聚簇索引涉及到复制数据以及创建表的新副本。但是,辅助索引仅包含索引键和主键的值。可以在不复制聚簇索引中的数据的情况下创建或删除此类索引。因为每个辅助索引都包含主键值的副本(用于在需要时访问聚集索引),所以当您更改主键的定义时,也会重新创建所有辅助索引。

删除二级索引很简单。只更新内部的InnoDB系统表和MySQL数据字典表,以反映索引不再存在的事实。InnoDB将用于索引的存储返回到包含它的表空间,以便新索引或附加表行可以使用该空间。

要向现有表添加二级索引,InnoDB将扫描该表,并按次级索引键列的值依次使用内存缓冲区和临时文件对行进行排序。然后以键值顺序构建B树,这比以随机顺序将行插入索引更有效。由于B树节点在填充时会被拆分,因此以这种方式构建索引会使索引具有更高的填充因子,从而使后续访问的效率更高。

14.13.6在线DDL和崩溃恢复

尽管在ALTER TABLE执行语句时服务器崩溃时不会丢失任何数据 ,但 对于聚簇索引二级索引崩溃恢复过程是不同的

如果服务器在创建InnoDB二级索引时崩溃,则在恢复时,MySQL将丢弃任何部分创建的索引。你必须重新运行ALTER TABLECREATE INDEX声明。

在创建InnoDB聚簇索引期间发生崩溃时,恢复更为复杂,因为表中的数据必须复制到全新的聚簇索引中。请记住,所有InnoDB表都存储为聚簇索引。

MySQL通过将原始InnoDB表中的现有数据复制到具有所需索引结构的临时表来创建新的聚集索引。一旦数据被完全复制到这个临时表中,原始表就会被重新命名为一个不同的临时表名。包含新聚集索引的临时表将使用原始表的名称进行重命名,并从数据库中删除原始表。

如果在创建新的聚集索引时发生系统崩溃,则不会丢失任何数据,但必须使用过程中存在的临时表来完成恢复过程。由于很少重新创建聚簇索引或重新定义大型表上的主键,或者在此操作过程中遇到系统崩溃,因此本手册未提供有关从此方案中恢复的信息。

14.13.7分区表的联机DDL

大多数ALTER TABLE分区子句不像普通的非分区InnoDB一样经历相同的内部在线DDL API 因此,对ALTER TABLE分区子句的在线支持各不相同。

下表显示了每个ALTER TABLE分区语句的联机状态 无论使用的在线DDL API如何,MySQL都会尝试尽可能减少数据复制和锁定。

  • 就地?列显示哪些操作允许该ALGORITHM=INPLACE子句。

  • 许可证并发DML?列显示哪些操作完全在线执行。您可以指定 LOCK=NONE在DDL操作期间声明允许并发DML。如果可能,MySQL会自动允许并发DML。

    对于支持的操作, ALGORITHM={COPY|INPLACE}可以指定 LOCK=SHARED在DDL操作期间声明允许并发查询。MySQL尽可能自动允许并发查询。

  • 备注栏提供了额外的信息,并说明有关的异常和依赖关系是/否等栏目的值。星号表示异常或依赖关系。

ALTER TABLE分区选项使用ALGORITHM=COPY或只允许 ALGORITHM=DEFAULT, LOCK=DEFAULT,使用COPY算法重新分区表换句话说,使用新的分区方案创建一个新的分区表。新创建的表包含由该ALTER TABLE 语句应用的所有更改,并将表数据复制到新的表结构中。

表14.11 ALTER TABLE分区子句的联机状态

分区子句 到位? 允许并发DML? 笔记
PARTITION BY 没有 没有 许可证ALGORITHM=COPYLOCK={DEFAULT|SHARED|EXCLUSIVE}
ADD PARTITION 没有 没有 只允许ALGORITHM=DEFAULTLOCK=DEFAULT不复制由RANGEor 分区的表的现有数据LIST针对由HASHor 分区的表允许并发查询LISTMySQL在持有共享锁的同时复制数据。
DROP PARTITION 没有 没有 只允许ALGORITHM=DEFAULTLOCK=DEFAULT不复制由RANGEor 分区的表的现有数据LIST
DISCARD PARTITION 没有 没有 只有许可证ALGORITHM=DEFAULTLOCK=DEFAULT
IMPORT PARTITION 没有 没有 只有许可证ALGORITHM=DEFAULTLOCK=DEFAULT
TRUNCATE PARTITION 不复制现有数据。它只是删除行; 它不会改变表本身或其任何分区的定义。
COALESCE PARTITION 没有 没有 只允许ALGORITHM=DEFAULTLOCK=DEFAULT并发查询被允许用于通过分区表HASHLIST,例如MySQL复制数据,而保持的共享锁。
REORGANIZE PARTITION 没有 没有 只允许ALGORITHM=DEFAULTLOCK=DEFAULT针对由LINEAR HASHor 分区的表允许并发查询LISTMySQL在保存共享元数据锁的同时从受影响的分区复制数据。
EXCHANGE PARTITION
ANALYZE PARTITION
CHECK PARTITION
OPTIMIZE PARTITION 没有 没有 ALGORITHMLOCK子句被忽略。重建整个表格。请参见 第22.3.4节“维护分区”
REBUILD PARTITION 没有 没有 只允许ALGORITHM=DEFAULTLOCK=DEFAULT针对由LINEAR HASHor 分区的表允许并发查询LISTMySQL在保存共享元数据锁的同时从受影响的分区复制数据。
REPAIR PARTITION
REMOVE PARTITIONING 没有 没有 许可证ALGORITHM=COPYLOCK={DEFAULT|SHARED|EXCLUSIVE}

ALTER TABLE 分区表上的 非分区联机操作遵循适用于常规表的相同规则。但是,ALTER TABLE对每个表分区执行联机操作,由于在多个分区上执行操作,这会导致系统资源需求增加。

有关ALTER TABLE分区子句的其他信息,请参见 分区选项第13.1.8.1节“ALTER TABLE分区操作”有关一般分区的信息,请参见 第22章分区

14.13.8在线DDL限制

以下限制适用于在线DDL操作:

  • 该表被复制,而不是在创建索引时使用快速索引创建TEMPORARY TABLE这已被报告为MySQL Bug#39833。

  • 当用户试图删除外键所需的索引时,InnoDB处理错误情况。参见 第B.3节,“服务器错误代码和信息”的信息错误有关1553

  • 如果表中存在或有限制,则不允许使用 ALTER TABLE子句 LOCK=NONEON...CASCADEON...SET NULL

  • 根据在线DDL操作的内部工作和声明LOCK条款,在 ALTER TABLEDDL操作的初始阶段和最终阶段,在线DDL操作可能需要在短时间内独占访问表格。因此,如果在执行插入,更新,删除或SELECT ... FOR UPDATE在表上执行长时间运行的事务,联机DDL操作可能会在完成之前等待; 如果在进行中启动类似的长时间运行事务,则在线DDL操作可能会在完成之前等待ALTER TABLE

  • 在运行联机DDL操作时,运行ALTER TABLE语句的线程会 应用从其他连接线程同时在同一个表上运行的DML操作联机日志应用DML操作时,即使重复条目只是临时的,并且在在线日志 ”中稍后输入时也会发生重复键入错误(错误1062(23000):重复条目这与外键约束检查的概念类似,在外键约束检查中 约束在事务期间必须保持。 InnoDB

  • OPTIMIZE TABLEInnoDB表映射到 ALTER TABLE操作以重建表并更新索引统计信息并释放聚簇索引中未使用的空间。二级索引的创建效率并不高,因为按照它们出现在主键中的顺序插入键。 OPTIMIZE TABLE通过添加在线DDL支持来重建常规InnoDB和分区 表。有关更多信息,请参见第14.13.1节“在线DDL概述”

  • InnoDBMySQL的5.6之前创建的表不支持ALTER TABLE ... ALGORITHM=INPLACE针对包括时间列(表DATEDATETIMETIMESTAMP),并使用尚未重建 ALTER TABLE ... ALGORITHM=COPY在这种情况下, ALTER TABLE ... ALGORITHM=INPLACE操作返回以下错误:

     
    错误1846(0A000):ALGORITHM = INPLACE不受支持。
    原因:无法更改列类型INPLACE。尝试ALGORITHM = COPY。
    
  • 这些限制通常适用于涉及表复制的大型表上的联机DDL操作:

    • 没有任何机制可以暂停联机DDL操作或限制联机DDL操作的I / O或CPU使用率。

    • 如果操作失败,则在线DDL操作的回滚可能很昂贵。

    • 长时间运行的在线DDL操作可能会导致复制滞后。在主站上运行之前,在线DDL操作必须在主站上完成运行。此外,在主站上的DDL操作完成后(Bug#73196),在主站上同时处理的DML仅在从站上处理。

    有关在大型表上运行联机DDL操作的其他信息,请参见 第14.13.2节“联机DDL性能,并发性和空间要求”

14.14 InnoDB启动选项和系统变量

表14.12 InnoDB选项和变量引用

名称 CMD线 选项文件 系统变量 状态变量 Var范围 动态
daemon_memcached_enable_binlog 全球 没有
daemon_memcached_engine_lib_name 全球 没有
daemon_memcached_engine_lib_path 全球 没有
daemon_memcached_option 全球 没有
daemon_memcached_r_batch_size 全球 没有
daemon_memcached_w_batch_size 全球 没有
FOREIGN_KEY_CHECKS
忽略-内置-的InnoDB 全球 没有
- 变量ignore_builtin_innodb 全球 没有
InnoDB的
innodb_adaptive_flushing 全球
innodb_adaptive_flushing_lwm 全球
innodb_adaptive_hash_index 全球
innodb_adaptive_hash_index_parts 全球 没有
innodb_adaptive_max_sleep_delay 全球
innodb_additional_mem_pool_size 全球 没有
innodb_api_bk_commit_interval 全球
innodb_api_disable_rowlock 全球 没有
innodb_api_enable_binlog 全球 没有
innodb_api_enable_mdl 全球 没有
innodb_api_trx_level 全球
innodb_autoextend_increment 全球
innodb_autoinc_lock_mode 全球 没有
Innodb_available_undo_logs 全球 没有
innodb_background_drop_list_empty 全球
Innodb_buffer_pool_bytes_data 全球 没有
Innodb_buffer_pool_bytes_dirty 全球 没有
innodb_buffer_pool_chunk_size 全球 没有
innodb_buffer_pool_dump_at_shutdown 全球
innodb_buffer_pool_dump_now 全球
innodb_buffer_pool_dump_pct 全球
Innodb_buffer_pool_dump_status 全球 没有
innodb_buffer_pool_filename 全球
innodb_buffer_pool_instances 全球 没有
innodb_buffer_pool_load_abort 全球
innodb_buffer_pool_load_at_startup 全球 没有
innodb_buffer_pool_load_now 全球
Innodb_buffer_pool_load_status 全球 没有
Innodb_buffer_pool_pages_data 全球 没有
Innodb_buffer_pool_pages_dirty 全球 没有
Innodb_buffer_pool_pages_flushed 全球 没有
Innodb_buffer_pool_pages_free 全球 没有
Innodb_buffer_pool_pages_latched 全球 没有
Innodb_buffer_pool_pages_misc 全球 没有
Innodb_buffer_pool_pages_total 全球 没有
Innodb_buffer_pool_read_ahead 全球 没有
Innodb_buffer_pool_read_ahead_evicted 全球 没有
Innodb_buffer_pool_read_ahead_rnd 全球 没有
Innodb_buffer_pool_read_requests 全球 没有
Innodb_buffer_pool_reads 全球 没有
Innodb_buffer_pool_resize_status 全球 没有
innodb_buffer_pool_size 全球 不定
Innodb_buffer_pool_wait_free 全球 没有
Innodb_buffer_pool_write_requests 全球 没有
innodb_change_buffer_max_size 全球
innodb_change_buffering 全球
innodb_change_buffering_debug 全球
innodb_checksum_algorithm 全球
innodb_checksums 全球 没有
innodb_cmp_per_index_enabled 全球
innodb_commit_concurrency 全球
innodb_compress_debug 全球
innodb_compression_failure_threshold_pct 全球
innodb_compression_level 全球
innodb_compression_pad_pct_max 全球
innodb_concurrency_tickets 全球
innodb_data_file_path中 全球 没有
Innodb_data_fsyncs 全球 没有
innodb_data_home_dir 全球 没有
Innodb_data_pending_fsyncs 全球 没有
Innodb_data_pending_reads 全球 没有
Innodb_data_pending_writes 全球 没有
Innodb_data_read 全球 没有
Innodb_data_reads 全球 没有
Innodb_data_writes 全球 没有
Innodb_data_written 全球 没有
Innodb_dblwr_pages_written 全球 没有
Innodb_dblwr_writes 全球 没有
innodb_default_row_format 全球
innodb_disable_resize_buffer_pool_debug 全球
innodb_disable_sort_file_cache 全球
innodb_doublewrite 全球 没有
innodb_fast_shutdown 全球
innodb_fil_make_page_dirty_debug 全球
innodb_file_format 全球
innodb_file_format_check 全球 没有
innodb_file_format_max 全球
innodb_file_per_table 全球
innodb_fill_factor 全球
innodb_flush_log_at_timeout 全球
的innodb_flush_log_at_trx_commit 全球
innodb_flush_method 全球 没有
innodb_flush_neighbors 全球
innodb_flush_sync 全球
innodb_flushing_avg_loops 全球
innodb_force_load_corrupted 全球 没有
innodb_force_recovery 全球 没有
innodb_ft_aux_table 全球
innodb_ft_cache_size 全球 没有
innodb_ft_enable_diag_print 全球
innodb_ft_enable_stopword 全球
innodb_ft_max_token_size 全球 没有
innodb_ft_min_token_size 全球 没有
innodb_ft_num_word_optimize 全球
innodb_ft_result_cache_limit 全球
innodb_ft_server_stopword_table 全球
innodb_ft_sort_pll_degree 全球 没有
innodb_ft_total_cache_size 全球 没有
innodb_ft_user_stopword_table
Innodb_have_atomic_builtins 全球 没有
innodb_io_capacity 全球
innodb_io_capacity_max 全球
innodb_large_prefix 全球
innodb_limit_optimistic_insert_debug 全球
innodb_lock_wait_timeout
innodb_locks_unsafe_for_binlog 全球 没有
innodb_log_buffer_size 全球 没有
innodb_log_checksum_algorithm 全球
innodb_log_checksums 全球
innodb_log_compressed_pa​​ges 全球
innodb_log_file_size 全球 没有
innodb_log_files_in_group 全球 没有
innodb_log_group_home_dir 全球 没有
Innodb_log_waits 全球 没有
innodb_log_write_ahead_size 全球
Innodb_log_write_requests 全球 没有
Innodb_log_writes 全球 没有
innodb_lru_scan_depth 全球
innodb_max_dirty_pages_pct 全球
innodb_max_dirty_pages_pct_lwm 全球
innodb_max_purge_lag 全球
innodb_max_purge_lag_delay 全球
innodb_max_undo_log_size 全球
innodb_merge_threshold_set_all_debug 全球
innodb_monitor_disable 全球
innodb_monitor_enable 全球
innodb_monitor_reset 全球
innodb_monitor_reset_all 全球
Innodb_num_open_files 全球 没有
innodb_numa_interleave 全球 没有
innodb_old_blocks_pct 全球
innodb_old_blocks_time 全球
innodb_online_alter_log_max_size 全球
innodb_open_files 全球 没有
innodb_optimize_fulltext_only 全球
innodb_optimize_point_storage 会议
Innodb_os_log_fsyncs 全球 没有
Innodb_os_log_pending_fsyncs 全球 没有
Innodb_os_log_pending_writes 全球 没有
Innodb_os_log_written 全球 没有
innodb_page_cleaners 全球 没有
Innodb_page_size 全球 没有
innodb_page_size 全球 没有
Innodb_pages_created 全球 没有
Innodb_pages_read 全球 没有
Innodb_pages_written 全球 没有
innodb_print_all_deadlocks 全球
innodb_purge_batch_size 全球
innodb_purge_rseg_truncate_frequency 全球
innodb_purge_threads 全球 没有
innodb_random_read_ahead 全球
innodb_read_ahead_threshold 全球
innodb_read_io_threads 全球 没有
innodb_read_only 全球 没有
innodb_replication_delay 全球
innodb_rollback_on_timeout 全球 没有
innodb_rollback_segments 全球
Innodb_row_lock_current_waits 全球 没有
Innodb_row_lock_time 全球 没有
Innodb_row_lock_time_avg 全球 没有
Innodb_row_lock_time_max 全球 没有
Innodb_row_lock_waits 全球 没有
Innodb_rows_deleted 全球 没有
Innodb_rows_inserted 全球 没有
Innodb_rows_read 全球 没有
Innodb_rows_updated 全球 没有
innodb_saved_pa​​ge_number_debug 全球
innodb_sort_buffer_size 全球 没有
innodb_spin_wait_delay 全球
innodb_stats_auto_recalc 全球
innodb_stats_include_delete_marked 全球
innodb_stats_method 全球
innodb_stats_on_metadata 全球
innodb_stats_persistent 全球
innodb_stats_persistent_sample_pages 全球
innodb_stats_sample_pages 全球
innodb_stats_transient_sample_pages 全球
InnoDB的状态文件
innodb_status_output 全球
innodb_status_output_locks 全球
innodb_strict_mode
innodb_support_xa
innodb_sync_array_size 全球 没有
innodb_sync_debug 全球 没有
innodb_sync_spin_loops 全球
innodb_table_locks
innodb_temp_data_file_path 全球 没有
innodb_thread_concurrency参数 全球
innodb_thread_sleep_delay 全球
innodb_tmpdir
Innodb_truncated_status_writes 全球 没有
innodb_trx_purge_view_update_only_debug 全球
innodb_trx_rseg_n_slots_debug 全球
innodb_undo_directory 全球 没有
innodb_undo_log_truncate 全球
innodb_undo_logs 全球
innodb_undo_tablespaces 全球 没有
innodb_use_native_aio 全球 没有
innodb_use_sys_malloc 全球 没有
innodb_version 全球 没有
innodb_write_io_threads 全球 没有
timed_mutexes 全球
UNIQUE_CHECKS

InnoDB命令选项

  • --ignore-builtin-innodb

    属性
    命令行格式 --ignore-builtin-innodb
    弃用
    系统变量 ignore_builtin_innodb
    范围 全球
    动态 没有
    类型 布尔

    在MySQL 5.1中,这个选项导致服务器表现得好像内置InnoDB不存在一样,这使得它InnoDB Plugin可以被使用。在MySQL 5.7中,InnoDB 它是默认的存储引擎,InnoDB Plugin并未被使用,所以这个选项被忽略。

  • --innodb[=value]

    属性
    命令行格式 --innodb[=value]
    弃用 5.7.5
    类型 列举
    默认 ON
    有效值

    OFF

    ON

    FORCE

    控制InnoDB存储引擎的加载(如果服务器是使用InnoDB支持编译的) 此选项有三态格式,可能值OFFONFORCE请参见 第5.5.1节“安装和卸载插件”

    禁用InnoDB,使用 --innodb=OFF--skip-innodb在这种情况下,因为默认的存储引擎是 InnoDB,服务器不会启动,除非您还使用 --default-storage-engine并将 --default-tmp-storage-engine默认设置为永久和TEMPORARY表的其他引擎的默认值

    InnoDB存储引擎可以不再被禁止,并且 --innodb=OFF--skip-innodb 选项弃用,没有任何效果。他们的使用导致警告。这些选项将在未来的MySQL版本中被删除。

  • --innodb-status-file

    属性
    命令行格式 --innodb-status-file
    类型 布尔
    默认 OFF

    控制是否InnoDB创建一个 在MySQL数据目录中命名的文件 如果启用,则 定期写入输出 innodb_status.pidInnoDBSHOW ENGINE INNODB STATUS该文件。

    默认情况下,该文件未被创建。要创建它,请使用该 选项启动 mysqld--innodb-status-file=1该文件在正常关机期间被删除。

  • --skip-innodb

    禁用InnoDB存储引擎。请参阅说明--innodb

InnoDB系统变量

  • daemon_memcached_enable_binlog

    属性
    命令行格式 --daemon-memcached-enable-binlog=#
    系统变量 daemon_memcached_enable_binlog
    范围 全球
    动态 没有
    类型 布尔
    默认 false

    主服务器上启用此选项 以将InnoDB memcached 插件(daemon_memcached)与MySQL 二进制日志一起使用该选项只能在服务器启动时设置。您还必须使用。在主服务器上启用MySQL二进制日志 --log-bin选项

    有关更多信息,请参见 第14.20.6节“InnoDB memcached插件和复制”

  • daemon_memcached_engine_lib_name

    属性
    命令行格式 --daemon-memcached-engine-lib-name=library
    系统变量 daemon_memcached_engine_lib_name
    范围 全球
    动态 没有
    类型 文件名
    默认 innodb_engine.so

    指定实现InnoDB memcached插件的共享库

    有关更多信息,请参见 第14.20.3节“设置InnoDB memcached插件”

  • daemon_memcached_engine_lib_path

    属性
    命令行格式 --daemon-memcached-engine-lib-path=directory
    系统变量 daemon_memcached_engine_lib_path
    范围 全球
    动态 没有
    类型 目录名称
    默认 NULL

    包含实现InnoDB memcached插件的共享库的目录的路径默认值为NULL,表示MySQL插件目录。除非memcached为位于MySQL插件目录之外的其他存储引擎指定插件,否则不需要修改此参数

    有关更多信息,请参见 第14.20.3节“设置InnoDB memcached插件”

  • daemon_memcached_option

    属性
    命令行格式 --daemon-memcached-option=options
    系统变量 daemon_memcached_option
    范围 全球
    动态 没有
    类型
    默认

    用于在启动时将空格分隔的memcached选项传递到底层的memcached内存对象缓存守护进程。例如,您可能会更改memcached的端口 侦听,减少同时连接的最大数量,更改键/值对的最大内存大小或启用错误日志的调试消息。

    有关使用细节请参见第14.20.3节“设置InnoDB memcached插件”有关memcached 选项的信息,请参阅memcached手册页。

  • daemon_memcached_r_batch_size

    属性
    命令行格式 --daemon-memcached-r-batch-size=#
    系统变量 daemon_memcached_r_batch_size
    范围 全球
    动态 没有
    类型 整数
    默认 1

    指定开始新事务之前要执行多少个memcached读取操作(get操作)COMMIT对应的 daemon_memcached_w_batch_size

    默认情况下,此值设置为1,以便通过SQL语句对表进行的任何更改对memcached操作立即可见 您可以增加它以减少系统中频繁提交的开销,因为系统只能通过memcached接口访问基础表 如果设置的值太大,撤消或重做数据量可能会导致一些存储开销,就像任何长时间运行的事务一样。

    有关更多信息,请参见 第14.20.3节“设置InnoDB memcached插件”

  • daemon_memcached_w_batch_size

    属性
    命令行格式 --daemon-memcached-w-batch-size=#
    系统变量 daemon_memcached_w_batch_size
    范围 全球
    动态 没有
    类型 整数
    默认 1

    指定多少memcached的写操作,如addsetincr,做一个前执行COMMIT ,以启动新的事务。对应的 daemon_memcached_r_batch_size

    默认情况下,此值设置为1,假设存储的数据对于在发生中断时保存很重要,并应立即执行。存储非关键数据时,可以增加此值以减少频繁落实的开销; N如果发生崩溃,最后的 -1个未提交的写入操作可能会丢失。

    有关更多信息,请参见 第14.20.3节“设置InnoDB memcached插件”

  • ignore_builtin_innodb

    属性
    命令行格式 --ignore-builtin-innodb
    弃用
    系统变量 ignore_builtin_innodb
    范围 全球
    动态 没有
    类型 布尔

    请参阅本节前面的InnoDB命令选项--ignore-builtin-innodb的说明

  • innodb_adaptive_flushing

    属性
    命令行格式 --innodb-adaptive-flushing=#
    系统变量 innodb_adaptive_flushing
    范围 全球
    动态
    类型 布尔
    默认 ON

    指定是否动态调整冲洗速度 脏页InnoDB 缓冲池中,根据工作负载。动态调整冲刷速率旨在避免I / O活动的爆发。该设置默认启用。有关更多信息请参见 第14.6.3.6节“配置InnoDB缓冲池刷新”有关通用I / O优化建议,请参见 第8.5.8节“优化InnoDB磁盘I / O”

  • innodb_adaptive_flushing_lwm

    属性
    命令行格式 --innodb-adaptive-flushing-lwm=#
    系统变量 innodb_adaptive_flushing_lwm
    范围 全球
    动态
    类型 整数
    默认 10
    最低限度 0
    最大 70

    定义表示启用自适应刷新重做日志容量百分比的低水位标记 有关更多信息,请参见 第14.6.3.7节“微调InnoDB缓冲池刷新”

  • innodb_adaptive_hash_index

    属性
    命令行格式 --innodb-adaptive-hash-index=#
    系统变量 innodb_adaptive_hash_index
    范围 全球
    动态
    类型 布尔
    默认 ON

    无论是InnoDB 适应性的散列索引被启用或禁用。根据您的工作负载,可能需要动态启用或禁用 自适应哈希索引以提高查询性能。由于自适应散列索引可能并不适用于所有工作负载,因此可以使用实际的工作负载对启用和禁用的基准进行基准测试。有关详细信息请参见 第14.4.3节“自适应散列索引”

    这个变量是默认启用的。您可以使用该SET GLOBAL语句修改此参数,而无需重新启动服务器。更改设置需要SUPER特权。您也可以--skip-innodb_adaptive_hash_index在服务器启动时使用 它来禁用它。

    禁用自适应散列索引会立即清空散列表。正常操作可以在哈希表清空时继续,并且执行使用哈希表的查询直接访问索引B树。当自适应散列索引重新启用时,在正常操作期间再次填充散列表。

  • innodb_adaptive_hash_index_parts

    属性
    命令行格式 --innodb-adaptive-hash-index-parts=#
    介绍 5.7.8
    系统变量 innodb_adaptive_hash_index_parts
    范围 全球
    动态 没有
    类型 数字
    默认 8
    最低限度 1
    最大 512

    划分自适应哈希索引搜索系统。每个索引都绑定到一个特定的分区,每个分区受独立的锁存器保护。

    在早期版本中,自适应散列索引搜索系统受单个锁存器(btr_search_latch)的保护,该锁存器可能成为争用点。通过引入该 innodb_adaptive_hash_index_parts选项,默认情况下,搜索系统分为8个部分。最大设置是512。

    相关信息请参见 第14.4.3节“自适应哈希索引”

  • innodb_adaptive_max_sleep_delay

    属性
    命令行格式 --innodb-adaptive-max-sleep-delay=#
    系统变量 innodb_adaptive_max_sleep_delay
    范围 全球
    动态
    类型 整数
    默认 150000
    最低限度 0
    最大 1000000

    允许根据当前工作量InnoDB自动调整innodb_thread_sleep_delay向上或向下的值 任何非零值都可以自动动态调整该 innodb_thread_sleep_delay值,直到innodb_adaptive_max_sleep_delay选项中指定的最大值 该值表示微秒数。这个选项在繁忙的系统中可用,有超过16个 InnoDB线程。(实际上,它对于具有数百或数千个同时连接的MySQL系统是最有价值的。)

    有关更多信息,请参见 第14.6.6节“为InnoDB配置线程并发”

  • innodb_additional_mem_pool_size

    属性
    命令行格式 --innodb-additional-mem-pool-size=#
    弃用 是(在5.7.4中删除)
    系统变量 innodb_additional_mem_pool_size
    范围 全球
    动态 没有
    类型 整数
    默认 8388608
    最低限度 2097152
    最大 4294967295

    内存池的字节大小InnoDB 用于存储数据字典信息和其他内部数据结构。您在应用程序中拥有的表格越多,您在此分配的内存就越多。如果InnoDB 此池中的内存不足,它将开始从操作系统分配内存,并将警告消息写入MySQL错误日志。默认值是8MB。

    这个变量与InnoDB 内部存储器分配器有关,如果innodb_use_sys_malloc被启用,它是未使用的 有关更多信息,请参见 第14.6.4节“为InnoDB配置内存分配器”

  • innodb_api_bk_commit_interval

    属性
    命令行格式 --innodb-api-bk-commit-interval=#
    系统变量 innodb_api_bk_commit_interval
    范围 全球
    动态
    类型 整数
    默认 5
    最低限度 1
    最大 1073741824

    几秒钟内 自动提交使用InnoDB memcached接口的空闲连接的频率 有关更多信息,请参见 第14.20.5.4节“控制InnoDB memcached插件的事务行为”

  • innodb_api_disable_rowlock

    属性
    命令行格式 --innodb-api-disable-rowlock=#
    系统变量 innodb_api_disable_rowlock
    范围 全球
    动态 没有
    类型 布尔
    默认 OFF

    InnoDB memcached 执行DML操作时,使用此选项可禁用行锁 默认情况下, innodb_api_disable_rowlock被禁用,这意味着memcached请求行锁getset 操作。innodb_api_disable_rowlock 启用时,分布式缓存请求表锁,而不是行锁。

    innodb_api_disable_rowlock不是动态的。它必须在mysqld命令行中指定或输入到MySQL配置文件中。插件安装时配置生效,这在MySQL服务器启动时发生。

    有关更多信息,请参见 第14.20.5.4节“控制InnoDB memcached插件的事务行为”

  • innodb_api_enable_binlog

    属性
    命令行格式 --innodb-api-enable-binlog=#
    系统变量 innodb_api_enable_binlog
    范围 全球
    动态 没有
    类型 布尔
    默认 OFF

    让您使用带有MySQL 二进制日志InnoDB memcached插件 有关更多信息,请参阅 启用InnoDB memcached二进制日志

  • innodb_api_enable_mdl

    属性
    命令行格式 --innodb-api-enable-mdl=#
    系统变量 innodb_api_enable_mdl
    范围 全球
    动态 没有
    类型 布尔
    默认 OFF

    锁定InnoDB memcached插件使用的表,以便它不能被DDL 通过SQL接口删除或更改有关更多信息,请参见 第14.20.5.4节“控制InnoDB memcached插件的事务行为”

  • innodb_api_trx_level

    属性
    命令行格式 --innodb-api-trx-level=#
    系统变量 innodb_api_trx_level
    范围 全球
    动态
    类型 整数
    默认 0

    控制memcached 接口处理的查询的事务 隔离级别常用名称对应的常量是:

    有关更多信息,请参见 第14.20.5.4节“控制InnoDB memcached插件的事务行为”

  • innodb_autoextend_increment

    属性
    命令行格式 --innodb-autoextend-increment=#
    系统变量 innodb_autoextend_increment
    范围 全球
    动态
    类型 整数
    默认 64
    最低限度 1
    最大 1000

    用于在自动扩展InnoDB 系统表空间文件变满时扩展大小的增量大小(以兆字节为单位)缺省值为64.有关信息,请参阅 系统表空间数据文件配置第14.7.1节“调整InnoDB系统表空间大小”

    innodb_autoextend_increment 设置不会影响 文件每表的表 空间文件或 常规表空间文件。无论innodb_autoextend_increment 设置如何,这些文件都是自动扩展的 最初的扩展是少量的,之后扩展以4MB为增量进行。

  • innodb_autoinc_lock_mode

    属性
    命令行格式 --innodb-autoinc-lock-mode=#
    系统变量 innodb_autoinc_lock_mode
    范围 全球
    动态 没有
    类型 整数
    默认 1
    有效值

    0

    1

    2

    用于生成 自动增量锁定模式传统,连续或交错的允许值分别为0,1或2。默认设置是1(连续)。有关每种锁定模式的特性,请参阅InnoDB AUTO_INCREMENT锁定模式

  • innodb_background_drop_list_empty

    属性
    命令行格式 --innodb-background-drop-list-empty=#
    介绍 5.7.10
    系统变量 innodb_background_drop_list_empty
    范围 全球
    动态
    类型 布尔
    默认 OFF

    启用 innodb_background_drop_list_empty调试选项有助于避免测试用例失败,方法是延迟表创建,直到背景下拉列表为空。例如,如果测试用例A将表t1放置在背景下拉列表中,则测试用例B将等待,直到创建表之前背景下拉列表为空 t1

  • innodb_buffer_pool_chunk_size

    属性
    命令行格式 --innodb-buffer-pool-chunk-size
    介绍 5.7.5
    系统变量 innodb_buffer_pool_chunk_size
    范围 全球
    动态 没有
    类型 整数
    默认 134217728
    最低限度 1048576
    最大 innodb_buffer_pool_size / innodb_buffer_pool_instances

    innodb_buffer_pool_chunk_size定义InnoDB缓冲池调整大小操作的块大小innodb_buffer_pool_size 参数是动态的,它允许您在不重新启动服务器的情况下调整缓冲池的大小。

    为避免在调整大小操作期间复制所有缓冲池页面,操作在 ”中执行 默认情况下, innodb_buffer_pool_chunk_size是128MB(134217728字节)。块中包含的页数取决于值 innodb_page_sizeinnodb_buffer_pool_chunk_size可以以1MB(1048576字节)为单位增加或减少。

    更改该innodb_buffer_pool_chunk_size时适用以下条件

    重要

    更改时应小心 innodb_buffer_pool_chunk_size,因为更改此值可自动增加缓冲池的大小。在更改之前 innodb_buffer_pool_chunk_size,计算它将会产生的影响, innodb_buffer_pool_size以确保生成的缓冲池大小可以接受。

    为避免潜在的性能问题,块(innodb_buffer_pool_size/ innodb_buffer_pool_chunk_size的数量不应超过1000个。

    有关更多信息请参见第14.6.3.2节“配置InnoDB缓冲池大小”

  • innodb_buffer_pool_dump_at_shutdown

    属性
    命令行格式 --innodb-buffer-pool-dump-at-shutdown=#
    系统变量 innodb_buffer_pool_dump_at_shutdown
    范围 全球
    动态
    类型 布尔
    默认(> = 5.7.7) ON
    默认(<= 5.7.6) OFF

    指定在MySQL服务器关闭时是否记录InnoDB 缓冲池中缓存的页面 ,以缩短下次重新启动时预热过程。通常与...结合使用 innodb_buffer_pool_load_at_startupinnodb_buffer_pool_dump_pct 选项定义要转储的最近使用的缓冲池页面的百分比。

    双方 innodb_buffer_pool_dump_at_shutdowninnodb_buffer_pool_load_at_startup默认启用。

    有关更多信息,请参见 第14.6.3.8节“保存和恢复缓冲池状态”

  • innodb_buffer_pool_dump_now

    属性
    命令行格式 --innodb-buffer-pool-dump-now=#
    系统变量 innodb_buffer_pool_dump_now
    范围 全球
    动态
    类型 布尔
    默认 OFF

    立即记录在InnoDB 缓冲池中缓存的页面 通常与...结合使用 innodb_buffer_pool_load_now

    有关更多信息,请参见 第14.6.3.8节“保存和恢复缓冲池状态”

  • innodb_buffer_pool_dump_pct

    属性
    命令行格式 --innodb-buffer-pool-dump-pct=#
    介绍 5.7.2
    系统变量 innodb_buffer_pool_dump_pct
    范围 全球
    动态
    类型 整数
    默认(> = 5.7.7) 25
    默认(<= 5.7.6) 100
    最低限度 1
    最大 100

    指定每个缓冲池读出和转储的最近使用页面的百分比。范围是1到100.默认值是25.例如,如果有4个缓冲池,每个缓冲池包含100个页面,并且 innodb_buffer_pool_dump_pct 设置为25,则将从每个缓冲池中转储25个最近使用的页面。

    innodb_buffer_pool_dump_pct 默认值的更改与innodb_buffer_pool_dump_at_shutdown and的 缺省值更改一致 innodb_buffer_pool_load_at_startup,这两个选项在MySQL 5.7中均默认启用。

  • innodb_buffer_pool_filename

    属性
    命令行格式 --innodb-buffer-pool-filename=file
    系统变量 innodb_buffer_pool_filename
    范围 全球
    动态
    类型 文件名
    默认 ib_buffer_pool

    指定保存由innodb_buffer_pool_dump_at_shutdown or 生成的表空间ID和页面ID列表的文件的名称 innodb_buffer_pool_dump_now表空间ID和页面ID以以下格式保存: space, page_id默认情况下,该文件被命名ib_buffer_pool并位于InnoDB数据目录中。必须指定相对于数据目录的非默认位置。

    可以在运行时使用SET 语句指定文件名称

    SET GLOBAL innodb_buffer_pool_filename = 'file_name';
    

    您还可以在启动时在启动字符串或MySQL配置文件中指定文件名。在启动时指定文件名时,该文件必须存在或 InnoDB将返回启动错误,指示没有此文件或目录。

    有关更多信息,请参见 第14.6.3.8节“保存和恢复缓冲池状态”

  • innodb_buffer_pool_instances

    属性
    命令行格式 --innodb-buffer-pool-instances=#
    系统变量 innodb_buffer_pool_instances
    范围 全球
    动态 没有
    类型(其他) 整数
    类型(Windows,32位平台) 整数
    默认(其他) 8 (or 1 if innodb_buffer_pool_size < 1GB
    默认(Windows,32位平台) (autosized)
    最小(其他) 1
    最低(Windows,32位平台) 1
    最大(其他) 64
    最大(Windows,32位平台) 64

    InnoDB 缓冲池划分 的区域数量对于缓冲池在数GB范围内的系统,通过在不同线程读取和写入缓存页面时减少争用,将缓冲池划分为不同的实例可以提高并发性。存储在缓冲池中或从中读取的每个页面都使用散列函数随机分配给其中一个缓冲池实例。每个缓冲池管理自己的空闲列表, 刷新列表LRU以及连接到缓冲池的所有其他数据结构,并受其自己的缓冲池互斥锁保护

    此选项仅在设置innodb_buffer_pool_size为1GB或更大时才有效 总缓冲池大小在所有缓冲池中分配。为了获得最佳效率,指定的组合 innodb_buffer_pool_instancesinnodb_buffer_pool_size ,使得每个缓冲池实例是至少为1GB。

    如下所述,32位Windows系统上的默认值取决于值 innodb_buffer_pool_size

    在所有其他平台上,当innodb_buffer_pool_size大于或等于1GB 时,默认值为8 否则,默认值为1。

    相关信息请参见 14.6.3.2节“配置InnoDB缓冲池大小”

  • innodb_buffer_pool_load_abort

    属性
    命令行格式 --innodb-buffer-pool-load-abort=#
    系统变量 innodb_buffer_pool_load_abort
    范围 全球
    动态
    类型 布尔
    默认 OFF

    中断恢复触发的InnoDB 缓冲池内容 的过程innodb_buffer_pool_load_at_startupinnodb_buffer_pool_load_now

    有关更多信息,请参见 第14.6.3.8节“保存和恢复缓冲池状态”

  • innodb_buffer_pool_load_at_startup

    属性
    命令行格式 --innodb-buffer-pool-load-at-startup=#
    系统变量 innodb_buffer_pool_load_at_startup
    范围 全球
    动态 没有
    类型 布尔
    默认(> = 5.7.7) ON
    默认(<= 5.7.6) OFF

    指定在MySQL服务器启动时,通过加载它在先前保存的相同页面InnoDB 缓冲池自动预热通常与...结合使用 innodb_buffer_pool_dump_at_shutdown

    双方 innodb_buffer_pool_dump_at_shutdowninnodb_buffer_pool_load_at_startup默认启用。

    有关更多信息,请参见 第14.6.3.8节“保存和恢复缓冲池状态”

  • innodb_buffer_pool_load_now

    属性
    命令行格式 --innodb-buffer-pool-load-now=#
    系统变量 innodb_buffer_pool_load_now
    范围 全球
    动态
    类型 布尔
    默认 OFF

    立即升温InnoDB 缓冲池通过装载一组数据页面,无需等待服务器重新启动。在基准测试期间将高速缓存恢复到已知状态,或者在运行查询报告或维护后,使MySQL服务器恢复正常工作负载,可能会很有用。

    有关更多信息,请参见 第14.6.3.8节“保存和恢复缓冲池状态”

  • innodb_buffer_pool_size

    属性
    命令行格式 --innodb-buffer-pool-size=#
    系统变量 innodb_buffer_pool_size
    范围 全球
    动态(> = 5.7.5)
    动态(<= 5.7.4) 没有
    类型(64位平台) 整数
    类型(32位平台) 整数
    默认(64位平台) 134217728
    默认(32位平台) 134217728
    最低(64位平台) 5242880
    最低(32位平台) 5242880
    最大(64位平台) 2**64-1
    最大(32位平台) 2**32-1

    缓冲池的 字节大小 InnoDB缓存表和索引数据的内存区域默认值是134217728字节(128MB)。最大值取决于CPU架构; 32位系统上的最大值为4294967295(2 32 -1),64位系统上的最大值为18446744073709551615(2 64 -1)。在32位系统上,CPU架构和操作系统可能会施加比实际最大值更小的实际最大值。当缓冲池的大小大于1GB时,设置 innodb_buffer_pool_instances 为大于1的值可以提高繁忙服务器的可伸缩性。

    较大的缓冲池需要较少的磁盘I / O才能多次访问相同的表数据。在专用数据库服务器上,您可以将缓冲池大小设置为机器物理内存大小的80%。配置缓冲池大小时请注意以下潜在问题,并准备在必要时缩小缓冲池的大小。

    • 物理内存竞争可能导致操作系统中的分页。

    • InnoDB 为缓冲区和控制结构保留额外的内存,因此总分配空间大约比指定的缓冲池大小大10%。

    • 缓冲池的地址空间必须是连续的,这可能是在装有特定地址的DLL的Windows系统上的一个问题。

    • 初始化缓冲池的时间大致与其大小成正比。在具有大缓冲池的实例上,初始化时间可能很重要。为了减少初始化时间,可以在服务器关闭时保存缓冲池状态,并在服务器启动时恢复它。请参见第14.6.3.8节“保存和恢复缓冲池状态”

    当您增加或减少缓冲池大小时,操作以块为单位执行。块大小由innodb_buffer_pool_chunk_size 配置选项定义 ,其默认值为128 MB。

    缓冲池大小必须始终等于或innodb_buffer_pool_chunk_size * 的倍数 innodb_buffer_pool_instances如果将缓冲池大小更改为不等于或等于innodb_buffer_pool_chunk_size * 倍数的 innodb_buffer_pool_instances值,则会自动将缓冲池大小调整为等于或 不小于指定缓冲池大小innodb_buffer_pool_chunk_size * 的倍数 innodb_buffer_pool_instances

    innodb_buffer_pool_size可以动态设置,这允许您在不重新启动服务器的情况下调整缓冲池的大小。Innodb_buffer_pool_resize_status 状态变量报告在线缓冲池的大小调整操作的状态。有关更多信息请参见 第14.6.3.2节“配置InnoDB缓冲池大小”

  • innodb_change_buffer_max_size

    属性
    命令行格式 --innodb-change-buffer-max-size=#
    系统变量 innodb_change_buffer_max_size
    范围 全球
    动态
    类型 整数
    默认 25
    最低限度 0
    最大 50

    InnoDB 更改缓冲区的 最大大小,占缓冲池总大小的百分比 您可能会增加MySQL服务器的这个数值,导致插入,更新和删除活动过多,或者为具有不变数据用于报告的MySQL服务器减少它。有关更多信息,请参见第14.4.2节“更改缓冲区”第14.6.5节“配置InnoDB更改缓冲区”有关通用I / O优化建议,请参见 第8.5.8节“优化InnoDB磁盘I / O”

  • innodb_change_buffering

    属性
    命令行格式 --innodb-change-buffering=#
    系统变量 innodb_change_buffering
    范围 全球
    动态
    类型 列举
    默认 all
    有效值

    none

    inserts

    deletes

    changes

    purges

    all

    是否InnoDB执行 更改缓冲,优化将写操作延迟到二级索引,以便可以顺序执行I / O操作。下表描述了允许的值。

    表14.13 innodb_change_buffering的允许值

    描述
    none 不要缓冲任何操作。
    inserts 缓冲区插入操作。
    deletes 缓冲区删除标记操作; 严格来说,在清除操作期间标记索引记录以供稍后删除的写入。
    changes 缓冲区插入和删除标记操作。
    purges 缓冲在后台发生的物理删除操作。
    all 默认值。缓冲区插入,删除标记操作和清除。

    有关更多信息,请参见 第14.4.2节“更改缓冲区”第14.6.5节“配置InnoDB更改缓冲区”有关通用I / O优化建议,请参见 第8.5.8节“优化InnoDB磁盘I / O”

  • innodb_change_buffering_debug

    属性
    命令行格式 --innodb-change-buffering-debug=#
    系统变量 innodb_change_buffering_debug
    范围 全球
    动态
    类型 整数
    默认 0
    最大 2

    设置InnoDB更改缓冲的调试标志值为1将强制更改缓冲区的所有更改。值为2会导致合并时崩溃。默认值为0表示未设置更改缓冲调试标志。此选项仅在使用CMake选项编译调试支持时可用WITH_DEBUG

  • innodb_checksum_algorithm

    属性
    命令行格式 --innodb-checksum-algorithm=#
    系统变量 innodb_checksum_algorithm
    范围 全球
    动态
    类型 列举
    默认(> = 5.7.7) crc32
    默认(<= 5.7.6) innodb
    有效值

    innodb

    crc32

    none

    strict_innodb

    strict_crc32

    strict_none

    指定如何生成和验证存储在表空间磁盘块中校验和是MySQL 5.7.7的默认值。 InnoDB crc32

    innodb_checksum_algorithm取代 innodb_checksums选项。为兼容性提供了以下值,直至并包括MySQL 5.7.6:

    • innodb_checksums=ON是一样的 innodb_checksum_algorithm=innodb

    • innodb_checksums=OFF是一样的 innodb_checksum_algorithm=none

    从MySQL 5.7.7开始,默认innodb_checksum_algorithm值为crc32, innodb_checksums=ON现在与之 相同 innodb_checksum_algorithm=crc32innodb_checksums=OFF仍然是一样的 innodb_checksum_algorithm=none

    为避免冲突,请删除对innodb_checksumsMySQL配置文件和启动脚本的引用

    该值innodb与早期版本的MySQL向后兼容。该值 crc32使用更快的算法计算每个修改块的校验和,并检查每个磁盘读取的校验和。它每次扫描32位数据块,这比innodb 校验和算法更快,每次扫描8位数据块。该值none在校验和字段中写入常数值,而不是基于块数据计算值。表空间中的块可以混合使用旧的,新的和不需要的校验和值,随着数据的修改逐渐更新; 一旦表空间中的块被修改为使用crc32 算法,关联的表不能被早期版本的MySQL读取。

    如果在表空间中遇到有效的但不匹配的校验和值,则校验和算法的严格形式会报告错误。建议您只在新实例中使用严格设置,以便第一次设置表空间。严格的设置速度会更快,因为它们不需要在磁盘读取期间计算所有校验和值。

    注意

    在MySQL 5.7.8之前,严格模式设置会 innodb_checksum_algorithm导致 InnoDB在遇到有效但不匹配的校验和时停止 在MySQL 5.7.8和更高版本中,只打印错误消息,并且如果页面具有有效的校验和innodb则该页面被接受为有效 crc32none

    下表显示了之间的区别 noneinnodbcrc32选项值,和他们同行的严格。noneinnodb并将crc32指定类型的校验和值写入每个数据块,但为了兼容性,在读取操作期间验证块时接受其他校验和值。严格设置也接受有效校验和值,但在遇到有效的不匹配校验和值时输出错误消息。如果InnoDB实例中的所有数据文件都以相同的innodb_checksum_algorithm创建, 那么使用严格形式可以使验证更快

    表14.14允许的innodb_checksum_algorithm值

    生成的校验和(写入时) 允许的校验和(阅读时)
    没有 一个常数。 任何校验的产生通过noneinnodbcrc32
    InnoDB的 用软件计算校验和,使用原始算法 InnoDB 任何校验的产生通过noneinnodbcrc32
    CRC32 使用该crc32算法计算校验和,可能使用硬件辅助。 任何校验的产生通过noneinnodbcrc32
    strict_none 一个常数 任何校验的产生通过noneinnodbcrc32InnoDB如果遇到有效但不匹配的校验和,则输出错误消息。
    strict_innodb 用软件计算校验和,使用原始算法 InnoDB 任何校验的产生通过noneinnodbcrc32InnoDB如果遇到有效但不匹配的校验和,则输出错误消息。
    strict_crc32 使用该crc32算法计算校验和,可能使用硬件辅助。 任何校验的产生通过noneinnodbcrc32InnoDB如果遇到有效但不匹配的校验和,则输出错误消息。

    MySQL Enterprise Backup 版本高达3.8.0不支持使用CRC32校验和的表空间备份。 MySQL Enterprise Backup在3.8.1中添加了CRC32校验和支持,但有一些限制。有关更多信息,请参阅 MySQL企业备份 3.8.1更改历史记录。

  • innodb_checksums

    属性
    命令行格式 --innodb-checksums
    弃用
    系统变量 innodb_checksums
    范围 全球
    动态 没有
    类型 布尔
    默认 ON

    InnoDB可以对从磁盘读取的所有表空间页面使用 校验和验证,以确保对硬件故障或损坏的数据文件提供额外的容错能力。此验证默认启用。在特殊情况下(例如运行基准测试时),此安全功能可以被禁用 --skip-innodb-checksums您可以指定使用该innodb_checksum_algorithm 选项计算校验和的方法

    innodb_checksums已弃用,取而代之 innodb_checksum_algorithm

    在MySQL 5.7.7之前,和之前innodb_checksums=ON 一样 innodb_checksum_algorithm=innodb从MySQL 5.7.7开始,innodb_checksum_algorithm 默认值是crc32,并且 与之 innodb_checksums=ON相同 innodb_checksum_algorithm=crc32innodb_checksums=OFF是一样的 innodb_checksum_algorithm=none

    innodb_checksums从配置文件和启动脚本中 删除任何选项以避免与之冲突innodb_checksum_algorithminnodb_checksums=OFF自动设置 innodb_checksum_algorithm=noneinnodb_checksums=ON被忽略并被任何其他设置覆盖 innodb_checksum_algorithm

  • innodb_cmp_per_index_enabled

    属性
    命令行格式 --innodb-cmp-per-index-enabled=#
    系统变量 innodb_cmp_per_index_enabled
    范围 全球
    动态
    类型 布尔
    默认 OFF
    有效值

    OFF

    ON

    INFORMATION_SCHEMA.INNODB_CMP_PER_INDEX 表中启用与索引压缩相关的统计信息 由于这些统计信息收集起来可能很昂贵,因此只能在与InnoDB 压缩相关的性能调整期间在开发,测试或从属实例上启用此选项

    有关更多信息,请参见 第24.31.6节“INFORMATION_SCHEMA INNODB_CMP_PER_INDEX和INNODB_CMP_PER_INDEX_RESET表”以及 第14.9.1.4节“运行时监控InnoDB表压缩”

  • innodb_commit_concurrency

    属性
    命令行格式 --innodb-commit-concurrency=#
    系统变量 innodb_commit_concurrency
    范围 全球
    动态
    类型 整数
    默认 0
    最低限度 0
    最大 1000

    可以同时提交线程值为0(默认值)允许同时提交任意数量的 事务

    innodb_commit_concurrency 在运行时间 的值不能从零变到非零,反之亦然。该值可以从一个非零值更改为另一个值。

  • innodb_compress_debug

    属性
    命令行格式 --innodb-compress-debug=#
    介绍 5.7.8
    系统变量 innodb_compress_debug
    范围 全球
    动态
    类型 列举
    默认 none
    有效值

    none

    zlib

    lz4

    lz4hc

    使用指定的压缩算法压缩所有表,而无需COMPRESSION 为每个表定义属性。该选项仅在使用CMake选项编译调试支持时可用 WITH_DEBUG

    有关相关信息,请参见 第14.9.2节“InnoDB页面压缩”

  • innodb_compression_failure_threshold_pct

    属性
    命令行格式 --innodb-compression-failure-threshold-pct=#
    系统变量 innodb_compression_failure_threshold_pct
    范围 全球
    动态
    类型 整数
    默认 5
    最低限度 0
    最大 100

    定义表格的压缩失败率阈值,以百分比表示,在这一点上,MySQL开始在压缩 页面中添加填充以避免昂贵的 压缩失败当这个阈值通过时,MySQL开始在每个新的压缩页面中留下额外的可用空间,动态调整可用空间的数量直到由指定的页面大小的百分比 innodb_compression_pad_pct_max值为零将禁用监视压缩效率并动态调整填充量的机制。

    有关更多信息,请参见 第14.9.1.6节“针对OLTP工作负载的压缩”

  • innodb_compression_level

    属性
    命令行格式 --innodb-compression-level=#
    系统变量 innodb_compression_level
    范围 全球
    动态
    类型 整数
    默认 6
    最低限度 0
    最大 9

    指定用于InnoDB 压缩表和索引的zlib压缩级别 较高的值可让您将更多数据放入存储设备,但压缩过程中CPU的开销会增加。当存储空间不重要时,较低的值可以减少CPU开销,或者您期望数据不是特别可压缩的。

    有关更多信息,请参见 第14.9.1.6节“针对OLTP工作负载的压缩”

  • innodb_compression_pad_pct_max

    属性
    命令行格式 --innodb-compression-pad-pct-max=#
    系统变量 innodb_compression_pad_pct_max
    范围 全球
    动态
    类型 整数
    默认 50
    最低限度 0
    最大 75

    指定每个压缩内可保留为空闲空间的最大百分比, 更新压缩表或索引并可重新压缩数据时,允许空间重新组织页面中的数据和修改日志仅适用于 innodb_compression_failure_threshold_pct 设置为非零值时,压缩失败通过截断点。

    有关更多信息,请参见 第14.9.1.6节“针对OLTP工作负载的压缩”

  • innodb_concurrency_tickets

    属性
    命令行格式 --innodb-concurrency-tickets=#
    系统变量 innodb_concurrency_tickets
    范围 全球
    动态
    类型 整数
    默认 5000
    最低限度 1
    最大 4294967295

    确定可以并发输入 线程InnoDB如果线程InnoDB数量已达到并发限制,则线程在尝试进入队列时放入队列当一个线程被允许进入时 InnoDB,它被赋予与其值相等 的许多 门票innodb_concurrency_tickets,并且线程可以InnoDB 自由进入和离开,直到其用完门票。在那之后,线程在下次尝试进入时再次受到并发检查(以及可能的排队)的影响 InnoDB默认值是5000。

    如果innodb_concurrency_tickets 值很小,那么只需要处理几行的小事务就可以与处理许多行的较大事务公平竞争。innodb_concurrency_tickets的缺点 是大型事务必须在完成之前多次遍历队列,这会延长完成任务所需的时间。

    具有较大的innodb_concurrency_tickets 值时,大型事务花费较少的时间来等待队列末尾的位置(由控制 innodb_thread_concurrency)并且更多时间检索行。大型交易还需要更少的队列来完成任务。较大的缺点 innodb_concurrency_tickets是,同时运行的大量事务可能会导致较小的事务处理,因此在执行前等待较长的时间。

    使用非零 innodb_thread_concurrency 值时,您可能需要innodb_concurrency_tickets向上或向下调整该 值以在较大和较小交易之间找到最佳平衡点。SHOW ENGINE INNODB STATUS 报告显示当前通过队列的执行事务的剩余票证数量。这些数据也可以从 表中TRX_CONCURRENCY_TICKETS列中获得 INFORMATION_SCHEMA.INNODB_TRX

    有关更多信息,请参见 第14.6.6节“为InnoDB配置线程并发”

  • innodb_data_file_path

    属性
    命令行格式 --innodb-data-file-path=name
    系统变量 innodb_data_file_path
    范围 全球
    动态 没有
    类型
    默认 ibdata1:12M:autoextend

    定义InnoDB 系统表空间 数据文件的名称,大小和属性 如果您未指定值 innodb_data_file_path,则默认行为是创建一个自动扩展数据文件,该文件略大于12MB,即已命名 ibdata1

    数据文件规范的完整语法包括文件名,文件大小autoextendmax属性:

    file_namefile_size[:autoextend [:max:max_file_size]]
    

    文件大小通过追加指定KB,MB或GB(1024MB) KMG大小值。如果以千字节(KB)为单位指定数据文件大小,请以1024的倍数进行此操作。否则,将KB值四舍五入为最接近兆字节(MB)的边界。文件大小的总和必须至少略大于12MB。

    为第一个系统表空间数据文件强制执行最小文件大小, 以确保有足够的空间存储双倍缓冲页面:

    单个文件的大小限制取决于您的操作系统。在支持大文件的操作系统上,您可以将文件大小设置为4GB以上。您还可以 使用原始磁盘分区作为数据文件

    autoextendmax 属性只能用于将最后一个指定的数据文件中使用 innodb_data_file_path 的设置。例如:

    的[mysqld]
    innodb_data_file_path中= ibdata1中:50M; ibdata2:12M:自动扩展:最大:500MB
    

    如果您指定了该autoextend选项,那么 InnoDB扩展数据文件(如果它的空闲空间不足)。autoextend增量是默认64MB。要修改增量,请更改 innodb_autoextend_increment 系统变量。

    系统表空间数据文件的完整目录路径是通过连接由innodb_data_home_dir定义的路径形成的 innodb_data_file_path

    有关配置系统表空间数据文件的更多信息,请参见 第14.6.1节“InnoDB启动配置”

  • innodb_data_home_dir

    属性
    命令行格式 --innodb-data-home-dir=dir_name
    系统变量 innodb_data_home_dir
    范围 全球
    动态 没有
    类型 目录名称

    InnoDB 系统表空间数据文件 的目录路径的公共部分 此设置启用不会影响每个表文件表空间 的位置 innodb_file_per_table默认值是MySQL data目录。如果您将该值指定为空字符串,则可以为其指定绝对文件路径 innodb_data_file_path

    指定值时需要尾部斜线 innodb_data_home_dir例如:

    的[mysqld]
    innodb_data_home_dir = / path / to / myibdata /
    

    有关相关信息,请参见 第14.6.1节“InnoDB启动配置”

  • innodb_deadlock_detect

    属性
    命令行格式 --innodb-deadlock-detect
    介绍 5.7.15
    系统变量 innodb_deadlock_detect
    范围 全球
    动态
    类型 布尔
    默认 ON

    该选项用于禁用死锁检测。在高并发系统上,当大量线程等待相同的锁时,死锁检测会导致速度下降。有时候,innodb_lock_wait_timeout 当死锁发生时,禁用死锁检测并依赖事务回滚设置可能更有效

    相关信息请参见 第14.5.5.2节“死锁检测和回滚”

  • innodb_default_row_format

    属性
    命令行格式 --innodb-default-row-format=#
    介绍 5.7.9
    系统变量 innodb_default_row_format
    范围 全球
    动态
    类型 列举
    默认 DYNAMIC
    有效值

    DYNAMIC

    COMPACT

    REDUNDANT

    innodb_default_row_format选项定义InnoDB 表格和用户创建的临时表格的默认行格式默认设置是DYNAMIC其他允许的值是 COMPACTREDUNDANTCOMPRESSED不支持在系统表空间中使用行格式 不能被定义为默认值。

    新创建的表格使用在未明确指定选项或使用选项innodb_default_row_format定义的行格式 ROW_FORMATROW_FORMAT=DEFAULT

    如果ROW_FORMAT未明确指定选项或者何时ROW_FORMAT=DEFAULT使用选项,则重建表的任何操作也会静默地将表格的行格式更改为由其定义的格式 innodb_default_row_format有关更多信息,请参见 第14.11.2节“指定表格的行格式”

    无论 设置如何,InnoDB由服务器创建的用于处理查询的 内部临时表都使用 DYNAMIC行格式 innodb_default_row_format

  • innodb_disable_sort_file_cache

    属性
    命令行格式 --innodb-disable-sort-file-cache=#
    系统变量 innodb_disable_sort_file_cache
    范围 全球
    动态
    类型 布尔
    默认 OFF

    为合并分类临时文件禁用操作系统文件系统缓存。效果是打开这样的文件等价于O_DIRECT

  • innodb_disable_resize_buffer_pool_debug

    属性
    命令行格式 --innodb-disable-resize-buffer-pool-debug=#
    介绍 5.7.6
    系统变量 innodb_disable_resize_buffer_pool_debug
    范围 全球
    动态
    类型 布尔
    默认 ON

    禁用调整InnoDB缓冲池的大小该选项仅在使用CMake选项编译调试支持时可用WITH_DEBUG

  • innodb_doublewrite

    属性
    命令行格式 --innodb-doublewrite
    系统变量 innodb_doublewrite
    范围 全球
    动态 没有
    类型 布尔
    默认 ON

    启用时(默认),InnoDB将所有数据存储两次,首先存储到 双写缓冲区,然后存入实际的 数据文件--skip-innodb_doublewrite当需要最高性能而不是关心数据完整性或可能的故障时,可以关闭此变量以 用于基准或案例。

    如果系统表空间数据文件(ibdata* 文件)位于支持原子写入的Fusion-io设备上,则会自动禁用双写缓冲,并将Fusion-io原子写入用于所有数据文件。由于双写缓冲区设置是全局性的,所以对于驻留在非Fusion-io硬件上的数据文件,也会禁用双写缓冲。此功能仅在Fusion-io硬件上受支持,并且仅在Linux上启用Fusion-io NVMFS。要充分利用此功能,建议使用innodb_flush_method设置O_DIRECT

    相关信息请参见 第14.4.7节“Doublewrite Buffer”

  • innodb_fast_shutdown

    属性
    命令行格式 --innodb-fast-shutdown[=#]
    系统变量 innodb_fast_shutdown
    范围 全球
    动态
    类型 整数
    默认 1
    有效值

    0

    1

    2

    InnoDB 关机模式。如果值为0,InnoDB在关闭之前执行 缓慢关闭,全部清除和更改缓冲区合并。如果该值为1(默认值),则InnoDB在关闭时跳过这些操作,这个过程称为 快速关闭如果该值为2,则InnoDB刷新其日志并关闭冷却,就好像MySQL崩溃了一样; 没有提交的事务丢失,但 崩溃恢复 操作使下一次启动需要更长的时间。

    在大量数据仍然被缓冲的极端情况下,缓慢关机可能需要几分钟甚至几小时。在MySQL主要版本之间升级或降级之前,请使用慢速关闭技术,以便在升级过程更新文件格式时全部准备好所有数据文件。

    使用innodb_fast_shutdown=2紧急或故障的情况下,获得绝对最快关机,如果数据是在损坏的风险。

  • innodb_fil_make_page_dirty_debug

    属性
    命令行格式 --innodb-fil-make-page-dirty-debug=#
    系统变量 innodb_fil_make_page_dirty_debug
    范围 全球
    动态
    类型 整数
    默认 0
    最大 2**32-1

    默认情况下,设置 innodb_fil_make_page_dirty_debug为表空间的ID会立即污染表空间的第一页。如果 innodb_saved_page_number_debug 设置为非默认值,innodb_fil_make_page_dirty_debug请将指定页面设置为 灰色。innodb_fil_make_page_dirty_debug选项仅在使用CMake选项编译调试支持时可用 WITH_DEBUG

  • innodb_file_format

    属性
    命令行格式 --innodb-file-format=#
    弃用 5.7.7
    系统变量 innodb_file_format
    范围 全球
    动态
    类型
    默认(> = 5.7.7) Barracuda
    默认(<= 5.7.6) Antelope
    有效值

    Antelope

    Barracuda

    InnoDB每个文件表格 空间 启用文件格式 支持的文件格式是 AntelopeBarracudaAntelope是原始 InnoDB文件格式,支持 REDUNDANTCOMPACT 行格式。Barracuda是新的文件格式,支持COMPRESSEDDYNAMIC行格式。

    COMPRESSEDDYNAMIC 行格式为InnoDB表格提供重要的存储功能 请参见 第14.11节“InnoDB行存储和行格式”

    更改 innodb_file_format设置不会影响现有InnoDB表空间文件的文件格式

    innodb_file_format 设置不适用于支持所有行格式表的常规表空间。请参见 14.7.9节,“InnoDB常规表空间”

    innodb_file_format 默认值改为Barracuda在MySQL 5.7。

    innodb_file_format 创建使用DYNAMIC行格式的表时,设置将被忽略 无论设置如何,使用DYNAMIC行格式创建的表格始终使用 Barracuda文件格式 innodb_file_format要使用COMPRESSED行格式, innodb_file_format必须设置为Barracuda

    innodb_file_format选项已被弃用,将在未来版本中删除。innodb_file_format选项的目的 是允许用户降级到InnoDBMySQL 5.1中的内置版本 现在MySQL 5.1已经到了其产品生命周期的最后阶段,这个选项提供的降级支持就不再需要了。

    有关更多信息,请参见 第14.10节“InnoDB文件格式管理”

  • innodb_file_format_check

    属性
    命令行格式 --innodb-file-format-check=#
    弃用 5.7.7
    系统变量 innodb_file_format_check
    范围 全球
    动态 没有
    类型 布尔
    默认 ON

    在服务器启动时,可以将此变量设置为1或0,以启用或禁用是否InnoDB检查系统表空间中文件格式标记 (例如)。如果检查标签并且高于当前版本支持的标签 ,则会发生错误并且 不会启动。如果标签不高,则将值设置 为文件格式标签。 AntelopeBarracudaInnoDBInnoDBInnoDBinnodb_file_format_max

    注意

    尽管默认值有时显示为 ONOFF,但始终使用数字值1或0在配置文件或命令行字符串中打开或关闭此选项。

    有关更多信息,请参见 第14.10.2.1节“InnoDB启动时的兼容性检查”

    innodb_file_format_check 选项与innodb_file_format选项一起被弃用 这两个选项将在未来版本中删除。

  • innodb_file_format_max

    属性
    命令行格式 --innodb-file-format-max=#
    弃用 5.7.7
    系统变量 innodb_file_format_max
    范围 全球
    动态
    类型
    默认(> = 5.7.9) Barracuda
    默认(<= 5.7.8) Antelope
    有效值

    Antelope

    Barracuda

    在服务器启动时,InnoDB将此变量的值设置为系统表空间中文件格式标记 (例如)。如果服务器创建或打开具有更高文件格式的表格,则将该值设置 为该格式。 AntelopeBarracudainnodb_file_format_max

    有关相关信息,请参见 第14.10节“InnoDB文件格式管理”

    innodb_file_format_max 选项与innodb_file_format选项一起被弃用 这两个选项将在未来版本中删除。

  • innodb_file_per_table

    属性
    命令行格式 --innodb-file-per-table
    系统变量 innodb_file_per_table
    范围 全球
    动态
    类型 布尔
    默认 ON

    innodb_file_per_table启用(默认),InnoDB存储数据和索引在一个单独的每个新创建的表 .ibd 文件,而不是系统表空间。当这些表被删除或截断时,这些表的存储将被回收。此设置启用 InnoDB表格压缩等功能 有关更多信息请参见 第14.7.4节“InnoDB文件每表表空间”

    启用 innodb_file_per_table也意味着 重建table()的情况下,ALTER TABLE 操作会将InnoDB表从系统表空间移动到单个.ibd文件此规则的一个例外是使用with with选项 放置在系统表空间中的表 这些表不受 设置的影响,只能移动到每个文件表的表空间ALTER TABLEALGORITHM=COPYTABLESPACE=innodb_systemCREATE TABLEALTER TABLEinnodb_file_per_tableALTER TABLE ... TABLESPACE=innodb_file_per_table

    innodb_file_per_table被禁用时, InnoDB存储在表和索引数据ibdata文件组成的 系统表空间此设置可降低诸如DROP TABLEor之 类操作的文件系统操作的性能开销 TRUNCATE TABLE对于整个存储设备专用于MySQL数据的服务器环境来说,这是最合适的。由于系统表空间永远不会缩小,并且在实例中的所有数据库之间共享,因此避免在空间受限系统上加载大量临时数据innodb_file_per_table被禁用。在这种情况下设置一个单独的实例,以便您可以删除整个实例来回收空间。

    innodb_file_per_table是默认启用的。如果与MySQL 5.5或5.1的向后兼容性值得关注,请考虑禁用它。这将防止 ALTER TABLEInnoDB表从系统表空间移动 到单个.ibd文件。

    innodb_file_per_table是动态的,可以设置ONOFF使用SET GLOBAL您也可以在MySQL 配置文件my.cnfmy.ini)中设置此选项, 但这需要关闭并重新启动服务器。

    动态更改该值需要 SUPER特权并立即影响所有连接的操作。

  • innodb_fill_factor

    属性
    命令行格式 --innodb-fill-factor=#
    介绍 5.7.5
    系统变量 innodb_fill_factor
    范围 全球
    动态
    类型 整数
    默认 100
    最低限度 10
    最大 100

    InnoDB在创建或重建索引时执行批量加载。这种索引创建方法被称为排序索引构建

    innodb_fill_factor定义在排序索引构建期间填充的每个B树页面上的空间的百分比,其余空间保留用于未来的索引增长。例如,设置 innodb_fill_factor为80将保留每个B-tree页面上20%的空间用于未来的指数增长。实际百分比可能有所不同。innodb_fill_factor设置被解释为提示而不是硬限制。

    一个innodb_fill_factor100设置叶免费为未来指数增长的聚簇索引页的空间的1/16。

    innodb_fill_factor适用于B树叶和非叶页。它不适用于用于TEXTBLOB输入的外部页面

    有关更多信息,请参见 第14.8.2.3节“分类索引构建”

  • innodb_flush_log_at_timeout

    属性
    系统变量 innodb_flush_log_at_timeout
    范围 全球
    动态
    类型 整数
    默认 1
    最低限度 1
    最大 2700

    每秒写入并刷新日志Ninnodb_flush_log_at_timeout 允许增加刷新之间的超时时间以减少刷新并避免影响二进制日志组落实的性能。默认设置为 innodb_flush_log_at_timeout 每秒一次。

  • innodb_flush_log_at_trx_commit

    属性
    命令行格式 --innodb-flush-log-at-trx-commit[=#]
    系统变量 innodb_flush_log_at_trx_commit
    范围 全球
    动态
    类型 列举
    默认 1
    有效值

    0

    1

    2

    控制提交操作的严格ACID合规性与 提交相关I / O操作重新排列并批量完成时可能实现的更高性能之间的平衡 您可以通过更改默认值来获得更好的性能,但在崩溃时您可能会丢失多达一秒的事务。

    • 完全符合ACID要求默认值1。使用此值,InnoDB 日志缓冲区的内容会 在每次事务提交时写入日志文件,并将日志文件 刷新到磁盘。

    • 值为0时,InnoDB日志缓冲区的内容 大约每秒写入日志文件一次,并将日志文件刷新到磁盘。事务提交时不执行从日志缓冲区到日志文件的写入操作。由于进程调度问题,每秒一次的刷新不能保证每秒发生一次。由于刷新到磁盘的操作大约每秒发生一次,因此任何mysqld进程崩溃都可能会丢失多达一秒的事务

    • 值为2时,InnoDB日志缓冲区的内容 会在每次事务提交后写入日志文件,并且日志文件每秒大约刷新一次到磁盘。由于进程调度问题,每秒一次的冲洗并不是100%保证每秒发生。由于刷新到磁盘的操作只能每秒发生一次,因此在操作系统崩溃或停电时,可能会丢失多达一秒的事务。

    • InnoDB日志刷新频率由控制 innodb_flush_log_at_timeout,它允许用户设置记录冲洗频率以 N秒(其中 N1 ... 2700,为1的默认值)。但是,任何 mysqld进程崩溃最多可以消除 N几秒钟的事务。

    • 独立于设置的 DDL更改和其他内部InnoDB 活动刷新InnoDB日志 innodb_flush_log_at_trx_commit

    • InnoDB 无论innodb_flush_log_at_trx_commit设置如何,崩溃恢复都可以工作 事务既可以完全应用,也可以完全擦除。

    对于InnoDB与事务一起使用的复制设置中的耐久性和一致性

    • 如果启用二进制日志记录,则设置 sync_binlog=1

    • 始终设置 innodb_flush_log_at_trx_commit=1

    警告

    许多操作系统和一些磁盘硬件欺骗了磁盘到磁盘的操作。他们可能会告诉 mysqld已经发生刷新,尽管没有刷新。在这种情况下,即使使用设置1,交易的持久性也不能保证,并且在最坏的情况下,停电可能会破坏 InnoDB数据。在SCSI磁盘控制器或磁盘本身中使用电池供电的磁盘缓存可加速文件刷新,并使操作更安全。您还可以尝试禁用硬件缓存中的磁盘写入缓存。

  • innodb_flush_method

    属性
    命令行格式 --innodb-flush-method=name
    系统变量 innodb_flush_method
    范围 全球
    动态 没有
    类型(Windows)
    类型(Unix)
    默认(Windows) NULL
    默认(Unix) NULL
    有效值(Windows)

    async_unbuffered

    normal

    unbuffered

    有效值(Unix)

    fsync

    O_DSYNC

    littlesync

    nosync

    O_DIRECT

    O_DIRECT_NO_FSYNC

    定义用于将 数据刷新InnoDB 数据文件日志文件的方法,这会影响I / O吞吐量。

    如果innodb_flush_method设置为 NULL在类Unix系统上,则fsync默认使用选项。如果 在Windows上innodb_flush_method设置为 NULL,则async_unbuffered默认使用选项。

    innodb_flush_method类Unix系统选项包括:

    • fsyncInnoDB使用fsync()系统调用来刷新数据和日志文件。fsync是默认设置。

    • O_DSYNCInnoDB用于 O_SYNC打开和刷新日志文件,并fsync()刷新数据文件。 InnoDBO_DSYNC直接使用 ,因为它在许多种类的Unix上都存在问题。

    • littlesync:此选项用于内部性能测试,目前不受支持。使用风险自负。

    • nosync:此选项用于内部性能测试,目前不受支持。使用风险自负。

    • O_DIRECTInnoDB 使用O_DIRECT(或 directio()在Solaris上)打开数据文件,并使用它fsync()来刷新数据和日志文件。该选项在一些GNU / Linux版本,FreeBSD和Solaris上可用。

    • O_DIRECT_NO_FSYNC 在刷新I / O期间InnoDB使用O_DIRECT,但在fsync()之后跳过 系统调用。此设置适用于某些类型的文件系统,但不适用于其他文件系统。例如,它不适用于XFS。如果您不确定您使用的文件系统是否需要某个文件系统 fsync(),例如保留所有文件元数据,请O_DIRECT改为使用

    innodb_flush_methodWindows系统选项包括:

    • async_unbufferedInnoDB使用Windows异步I / O和非缓冲I / O。async_unbuffered 是Windows系统上的默认设置。

      在Windows上的4K扇区硬盘驱动器上运行MySQL服务器不支持async_unbuffered解决方法是使用 innodb_flush_method=normal

    • normalInnoDB使用模拟异步I / O和缓冲I / O。

    • unbufferedInnoDB 使用模拟异步I / O和非缓冲I / O。

    每个设置如何影响性能取决于硬件配置和工作负载。对特定配置进行基准测试,以确定要使用的设置,还是保持默认设置。检查 Innodb_data_fsyncs状态变量以查看fsync()每个设置的总体呼叫数量 工作负载中的读写操作可能会影响设置的执行方式。例如,在具有硬件RAID控制器和电池备份写缓存的系统上, O_DIRECT可以帮助避免InnoDB缓冲池与操作系统文件系统缓存之间的双重缓冲在某些系统上 InnoDB数据和日志文件位于SAN上,这是默认值,或者O_DSYNC对于大多数SELECT语句而言,读取繁重的工作负载可能会更快 始终使用反映您生产环境的硬件和工作负载来测试此参数。有关通用I / O优化建议,请参见 第8.5.8节“优化InnoDB磁盘I / O”

  • innodb_flush_neighbors

    属性
    命令行格式 --innodb-flush-neighbors
    系统变量 innodb_flush_neighbors
    范围 全球
    动态
    类型 列举
    默认 1
    有效值

    0

    1

    2

    指定是否冲洗从一个页面InnoDB 缓冲池也可以清空其他脏页在相同的 程度

    • 默认值1将从缓冲池中清除相同范围内的连续脏页。

    • 设置为0将 innodb_flush_neighbors关闭,并且不会从缓冲池中清除其他脏页。

    • 设置为2会从缓冲池中以相同范围刷新脏页。

    当表格数据存储在传统的 HDD存储设备上时, 与在不同时间冲刷单独页面相比,在一个操作中刷新这样的相邻页面减少了I / O开销(主要用于磁盘搜索操作)。对于存储在SSD上的表格数据 ,查找时间不是一个重要因素,您可以关闭此设置以分散写入操作。有关相关信息,请参见 第14.6.3.7节“微调InnoDB缓冲池刷新”

  • innodb_flush_sync

    属性
    命令行格式 --innodb-flush-sync=#
    介绍 5.7.8
    系统变量 innodb_flush_sync
    范围 全球
    动态
    类型 布尔
    默认 ON

    innodb_flush_sync参数默认情况下处于启用状态,导致 innodb_io_capacity设置在检查点发生的I / O活动突发中被忽略 要遵守设置InnoDB定义的后台I / O活动 限制innodb_io_capacity,请禁用innodb_flush_sync

    有关相关信息,请参见 第14.6.9节“配置InnoDB主线程I / O速率”

  • innodb_flushing_avg_loops

    属性
    命令行格式 --innodb-flushing-avg-loops=#
    系统变量 innodb_flushing_avg_loops
    范围 全球
    动态
    类型 整数
    默认 30
    最低限度 1
    最大 1000

    迭代次数InnoDB保持之前计算的刷新状态快照,控制 自适应刷新响应变化 工作负载的速度随着工作负载的变化,增加值会使冲洗操作的速度 平稳且逐渐变化。降低该值会使自适应冲洗快速适应工作负载的变化,如果工作负载突然增加或减少,可能会导致冲刷活动出现峰值。

    有关相关信息,请参见 第14.6.3.7节“微调InnoDB缓冲池刷新”

  • innodb_force_load_corrupted

    属性
    命令行格式 --innodb-force-load-corrupted
    系统变量 innodb_force_load_corrupted
    范围 全球
    动态 没有
    类型 布尔
    默认 OFF

    允许InnoDB在启动时加载标记为已损坏的表。仅在故障排除期间使用,以恢复无法访问的数据。故障排除完成后,请禁用此设置并重新启动服务器。

  • innodb_force_recovery

    属性
    命令行格式 --innodb-force-recovery=#
    系统变量 innodb_force_recovery
    范围 全球
    动态 没有
    类型 整数
    默认 0
    最低限度 0
    最大 6

    崩溃恢复 模式,通常只有在认真排除故障的情况下更改。可能的值为0到6.有关这些值的含义和重要信息 innodb_force_recovery,请参见 第14.21.2节“强制InnoDB恢复”

    警告

    在紧急情况下,只能将此变量设置为大于0的值,以便您可以启动 InnoDB并转储您的表。作为安全措施,大于0 InnoDB防止 INSERTUPDATE或者 DELETE操作 innodb_force_recoveryinnodb_force_recovery设置为4或更大的位置InnoDB进入只读模式。

    这些限制可能会导致复制管理命令失败并显示错误,如复制选项(如 --relay-log-info-repository=TABLE--master-info-repository=TABLE 将信息存储在InnoDB表中)。

  • innodb_ft_aux_table

    属性
    命令行格式 --innodb-ft-aux-table=# (> = 5.7.2)
    系统变量 innodb_ft_aux_table
    范围 全球
    动态
    类型

    指定InnoDB 包含FULLTEXT索引的限定名称该变量用于诊断目的。

    当您在格式这个变量设置为名称 表格 ,和 显示有关指定表的搜索索引信息。 db_name/table_nameINFORMATION_SCHEMAINNODB_FT_INDEX_TABLEINNODB_FT_INDEX_CACHEINNODB_FT_CONFIGINNODB_FT_DELETEDINNODB_FT_BEING_DELETED

    有关更多信息,请参见 第14.15.4节“InnoDB INFORMATION_SCHEMA全文索引表”

  • innodb_ft_cache_size

    属性
    命令行格式 --innodb-ft-cache-size=#
    系统变量 innodb_ft_cache_size
    范围 全球
    动态 没有
    类型 整数
    默认 8000000
    最低限度 1600000
    最大 80000000

    以字节为单位分配的内存用于 InnoDB FULLTEXT搜索索引缓存,该缓存在创建InnoDB FULLTEXT索引时在内存中保存已分析的文档索引插入和更新仅在innodb_ft_cache_size达到大小限制时才提交给磁盘 innodb_ft_cache_size以每个表为基础定义高速缓存大小。要为所有表设置全局限制,请参阅 innodb_ft_total_cache_size

    有关更多信息,请参阅 InnoDB全文索引缓存

  • innodb_ft_enable_diag_print

    属性
    命令行格式 --innodb-ft-enable-diag-print=#
    系统变量 innodb_ft_enable_diag_print
    范围 全球
    动态
    类型 布尔
    默认 OFF

    是否启用附加的全文搜索(FTS)诊断输出。此选项主要用于高级FTS调试,对大多数用户不感兴趣。输出打印到错误日志中,并包含以下信息:

    • FTS索引同步进度(达到FTS高速缓存限制时)。例如:

      用于表测试的FTS SYNC,删除的计数:100大小:10000字节
      同步字:100
      
    • FTS优化进展。例如:

      FTS开始优化测试
      FTS_OPTIMIZE:优化“mysql”
      FTS_OPTIMIZE:处理“mysql”
      
    • FTS指数建立进度。例如:

      处理的文档数量:1000
      
    • 对于FTS查询,将打印查询解析树,文字权重,查询处理时间和内存使用情况。例如:

      FTS搜索处理时间:1秒:100毫秒:行10000
      全搜索内存:245666(字节),行:10000
      
  • innodb_ft_enable_stopword

    属性
    命令行格式 --innodb-ft-enable-stopword=#
    系统变量 innodb_ft_enable_stopword
    范围 全球
    动态
    类型 布尔
    默认 ON

    指定 在索引创建时一组 停用词InnoDB FULLTEXT索引关联如果该 innodb_ft_user_stopword_table 选项已设置,则停用词将从该表中获取。否则,如果 innodb_ft_server_stopword_table 选项已设置,则停用词将从该表中提取。否则,使用内置的一组默认停用词。

    有关更多信息,请参见 第12.9.4节“全文停用词”

  • innodb_ft_max_token_size

    属性
    命令行格式 --innodb-ft-max-token-size=#
    系统变量 innodb_ft_max_token_size
    范围 全球
    动态 没有
    类型 整数
    类型 整数
    默认 84
    默认 84
    最低限度 10
    最低限度 10
    最大(> = 5.7.3) 84
    最大(<= 5.7.2) 252
    最大 84

    存储在InnoDB FULLTEXT索引中的单词的最大字符长度 对此值设置限制可以减小索引的大小,从而加快查询速度,方法是省略长关键字或任意字母集合,这些字母不是真正的单词,也不可能是搜索术语。

    有关更多信息,请参见 第12.9.6节“微调MySQL全文搜索”

  • innodb_ft_min_token_size

    属性
    命令行格式 --innodb-ft-min-token-size=#
    系统变量 innodb_ft_min_token_size
    范围 全球
    动态 没有
    类型 整数
    默认 3
    最低限度 0
    最大 16

    存储在InnoDB FULLTEXT索引中的单词的最小长度 增加此值可减小索引的大小,从而通过省略在搜索上下文中不太可能显着的常见单词(如英语单词ato ”)加快查询速度对于使用CJK(中文,日文,韩文)字符集的内容,请指定值1。

    有关更多信息,请参见 第12.9.6节“微调MySQL全文搜索”

  • innodb_ft_num_word_optimize

    属性
    命令行格式 --innodb-ft-num-word-optimize=#
    系统变量 innodb_ft_num_word_optimize
    范围 全球
    动态
    类型 整数
    默认 2000

    索引OPTIMIZE TABLE 每次操作 期间要处理的字数 InnoDB FULLTEXT由于对包含全文搜索索引的表进行大容量插入或更新操作可能需要大量索引维护才能包含所有更改,因此您可能会执行一系列OPTIMIZE TABLE 语句,每个语句都会从最后一次离开的位置开始。

    有关更多信息,请参见 第12.9.6节“微调MySQL全文搜索”

  • innodb_ft_result_cache_limit

    属性
    命令行格式 --innodb-ft-result-cache-limit=#
    介绍 5.7.2
    系统变量 innodb_ft_result_cache_limit
    范围 全球
    动态
    类型(Windows,> = 5.7.2,<= 5.7.3) 整数
    类型(Unix,64位平台,> = 5.7.2,<= 5.7.3) 整数
    类型(Unix,32位平台,> = 5.7.2,<= 5.7.3) 整数
    类型(> = 5.7.4) 整数
    默认值(Windows,> = 5.7.2,<= 5.7.3) 2000000000
    缺省值(Unix,64位平台,> = 5.7.2,<= 5.7.3) 2000000000
    缺省值(Unix,32位平台,> = 5.7.2,<= 5.7.3) 2000000000
    默认(> = 5.7.4) 2000000000
    最小值(Windows,> = 5.7.2,<= 5.7.3) 1000000
    最小(Unix,64位平台,> = 5.7.2,<= 5.7.3) 1000000
    最小(Unix,32位平台,> = 5.7.2,<= 5.7.3) 1000000
    最小(> = 5.7.4) 1000000
    最大值(Windows,> = 5.7.2,<= 5.7.3) 2**32-1
    最大(Unix,64位平台,> = 5.7.2,<= 5.7.3) 2**64-1
    最大(Unix,32位平台,> = 5.7.2,<= 5.7.3) 2**32-1
    最大(> = 5.7.4) 2**32-1

    InnoDB每全文搜索查询或每个线程全文搜索查询结果高速缓存限制(以字节为单位定义)。InnoDB 在内存中处理中间和最终的全文搜索查询结果。用于 innodb_ft_result_cache_limit在全文搜索查询结果缓存中放置大小限制,以避免在非常大InnoDB的全文搜索查询结果(例如数百万或数亿行)情况下耗用过多的内存 在处理全文搜索查询时,会根据需要分配内存。如果达到了结果缓存大小限制,则会返回错误,指示查询超出了允许的最大内存。

    innodb_ft_result_cache_limit所有平台类型和位大小 的最大值 是2 ** 32-1。

  • innodb_ft_server_stopword_table

    属性
    命令行格式 --innodb-ft-server-stopword-table=db_name/table_name
    系统变量 innodb_ft_server_stopword_table
    范围 全球
    动态
    类型
    默认 NULL

    该选项用于InnoDB FULLTEXT为所有InnoDB指定您自己的 索引停用词列表要为特定InnoDB配置您自己的停用词列表 ,请使用 innodb_ft_user_stopword_table

    设置innodb_ft_server_stopword_table为包含停用词列表的表格名称,格式为 db_name/table_name

    在配置之前,停用词表必须存在 innodb_ft_server_stopword_tableinnodb_ft_enable_stopword必须启用并且innodb_ft_server_stopword_table必须配置选项才能创建 FULLTEXT索引。

    停用词表必须是InnoDB包含VARCHAR名为的单个value

    有关更多信息,请参见 第12.9.4节“全文停用词”

  • innodb_ft_sort_pll_degree

    属性
    命令行格式 --innodb-ft-sort-pll-degree=#
    系统变量 innodb_ft_sort_pll_degree
    范围 全球
    动态 没有
    类型 整数
    默认 2
    最低限度 1
    最大 32

    InnoDB FULLTEXT 在构建搜索索引 用于并行索引和标记索引中文本的线程数

    有关相关信息,请参见 第14.8.2.4节“InnoDB FULLTEXT索引”innodb_sort_buffer_size

  • innodb_ft_total_cache_size

    属性
    命令行格式 --innodb-ft-total-cache-size=#
    介绍 5.7.2
    系统变量 innodb_ft_total_cache_size
    范围 全球
    动态 没有
    类型 整数
    默认 640000000
    最低限度 32000000
    最大 1600000000

    InnoDB所有表格的全文搜索索引缓存 的总内存(以字节为单位) 创建大量表格,每个表格都有一个 FULLTEXT搜索索引,可能会消耗大部分可用内存。 innodb_ft_total_cache_size 为所有全文搜索索引定义全局内存限制,以帮助避免过多的内存消耗。如果通过索引操作达到全局限制,则触发强制同步。

    有关更多信息,请参阅 InnoDB全文索引缓存

  • innodb_ft_user_stopword_table

    属性
    命令行格式 --innodb-ft-user-stopword-table=db_name/table_name
    系统变量 innodb_ft_user_stopword_table
    范围 全球,会议
    动态
    类型
    默认 NULL

    该选项用于InnoDB FULLTEXT在特定表格上指定您自己的 索引停用词列表。要为所有InnoDB配置您自己的停用词列表,请使用 innodb_ft_server_stopword_table

    设置innodb_ft_user_stopword_table为包含停用词列表的表格名称,格式为 db_name/table_name

    在配置之前,停用词表必须存在 innodb_ft_user_stopword_tableinnodb_ft_enable_stopword必须启用并且innodb_ft_user_stopword_table必须在创建FULLTEXT 索引之前进行配置

    停用词表必须是InnoDB包含VARCHAR名为的单个value

    有关更多信息,请参见 第12.9.4节“全文停用词”

  • innodb_io_capacity

    属性
    命令行格式 --innodb-io-capacity=#
    系统变量 innodb_io_capacity
    范围 全球
    动态
    类型(64位平台) 整数
    类型(32位平台) 整数
    默认(64位平台) 200
    默认(32位平台) 200
    最低(64位平台) 100
    最低(32位平台) 100
    最大(64位平台) 2**64-1
    最大(32位平台) 2**32-1

    innodb_io_capacity 参数设置InnoDB后台任务每秒执行的I / O操作数的上限,例如刷新缓冲池中的 页面以及合并来自更改缓冲区的数据

    innodb_io_capacity限制是所有缓冲池实例的总限制。当刷新脏页时,限制在缓冲池实例中平均分配。

    innodb_io_capacity应设置为大约系统每秒可执行的I / O操作数。理想情况下,保持尽可能低的设置,但不要太低以至于背景活动落后。如果该值太高,则数据将从缓冲池中删除,并且插入缓冲区太快而无法进行缓存以提供显着的优势。

    缺省值为200.对于能够提高I / O速率的繁忙系统,可以设置较高的值以帮助服务器处理与高速行更改相关的后台维护工作。

    通常,可以根据用于InnoDB I / O 的驱动器数量增加该值例如,您可以增加使用多个磁盘或固态磁盘(SSD)的系统上的值。

    对于较低端的SSD,默认设置为200通常就足够了。例如,对于更高端的总线连接的SSD,考虑更高的设置,例如1000。对于具有单个5400 RPM或7200 RPM驱动器的系统,您可能会将该值降低到100,这代表可以执行大约100 IOPS的旧一代磁盘驱动器可用的每秒I / O操作(IOPS)的估计比例。

    尽管您可以指定一个非常高的值,例如100万,但实际上,这样大的值几乎没有好处。通常,建议不要使用20000或更高的值,除非您已经证明较低的值不足以满足您的工作负载。

    调整时考虑写入工作量 innodb_io_capacity大写入工作负载的系统很可能从更高的设置中受益。对于写入工作量小的系统,较低的设置可能就足够了。

    您可以将innodb_io_capacity任何数字设置为100或更大,以达到由其定义的最大值 innodb_io_capacity_maxinnodb_io_capacity可以在MySQL选项文件(my.cnfmy.ini)中设置,也可以使用SET GLOBAL需要SUPER特权语句 动态更改

    innodb_flush_sync 配置选项使 innodb_io_capacity发生在检查点I / O活动的脉冲串期间被忽略设置。 innodb_flush_sync是默认启用的。

    有关更多信息请参见第14.6.9节“配置InnoDB主线程I / O速率”有关InnoDBI / O性能的一般信息 ,请参见 第8.5.8节“优化InnoDB磁盘I / O”

  • innodb_io_capacity_max

    属性
    命令行格式 --innodb-io-capacity-max=#
    系统变量 innodb_io_capacity_max
    范围 全球
    动态
    类型(Windows,64位平台) 整数
    类型(Unix,64位平台) 整数
    类型(32位平台) 整数
    默认(Windows,64位平台) see description
    默认(Unix,64位平台) see description
    默认(32位平台) see description
    最低(Windows,64位平台) 100
    最低(Unix,64位平台) 100
    最低(32位平台) 100
    最大(Windows,64位平台) 2**32-1
    最大(Unix,64位平台) 2**64-1
    最大(32位平台) 2**32-1

    如果冲洗活动落后,InnoDB 可以冲洗的积极性超过了限制 innodb_io_capacityinnodb_io_capacity_max定义了InnoDB在这种情况下背景任务每秒执行的I / O操作的数量的上限

    innodb_io_capacity_max 设置是所有缓冲池实例的总限制。

    如果您innodb_io_capacity在启动时指定 设置,但不指定值for innodb_io_capacity_max,则 innodb_io_capacity_max默认为值的两倍 innodb_io_capacity,最小值为2000。

    配置时innodb_io_capacity_max,两倍innodb_io_capacity 通常是一个很好的起点。默认值2000适用于使用固态磁盘(SSD)或多个常规磁盘驱动器的工作负载。对于不使用SSD或多个磁盘驱动器的工作负载,2000的设置可能过高,并且可能会导致过多的刷新。对于单个普通磁盘驱动器,建议在200到400之间设置。对于高端,总线连接的SSD,考虑更高的设置,如2500.与 innodb_io_capacity设置一样,尽可能降低设置,但不要太低,以至于如果必要的话InnoDB不能超出innodb_io_capacity极限。

    调整时考虑写入工作量 innodb_io_capacity_max大写入工作负载的系统可能受益于更高的设置。对于写入工作量小的系统,较低的设置可能就足够了。

    innodb_io_capacity_max不能设置为低于该 innodb_io_capacity值的值。

    设置 innodb_io_capacity_maxDEFAULT使用 SET 语句(SET GLOBAL innodb_io_capacity_max=DEFAULT)设置 innodb_io_capacity_max为最大值。

    有关相关信息,请参见 第14.6.3.7节“微调InnoDB缓冲池刷新”

  • innodb_large_prefix

    属性
    命令行格式 --innodb-large-prefix
    弃用 5.7.7
    系统变量 innodb_large_prefix
    范围 全球
    动态
    类型 布尔
    默认(> = 5.7.7) ON
    默认(<= 5.7.6) OFF

    启用此选项时,对于InnoDB使用DYNAMICCOMPRESSED 行格式的表,允许使用 长度超过767个字节(最多3072个字节)的索引键前缀 请参阅第14.8.1.7节“InnoDB表的限制”,了解与各种设置下的索引键前缀相关的最大值。

    对于使用REDUNDANTCOMPACT 行格式的,此选项不会影响允许的索引键前缀长度。

    innodb_large_prefix在MySQL 5.7中默认启用。此更改与MySQL 5.7中默认innodb_file_format设置 的默认值更改一致 Barracuda总之,这些默认值更改允许在使用DYNAMICCOMPRESSED 行格式时创建更大的索引键前缀 如果任一选项设置为非默认值,则会自动截断大于767字节的索引键前缀。

    innodb_large_prefix已弃用,将在未来版本中删除。 innodb_large_prefix在MySQL 5.5中引入,以禁用大型索引键前缀,以便与InnoDB不支持大型索引键前缀的早期版本兼容

  • innodb_limit_optimistic_insert_debug

    属性
    命令行格式 --innodb-limit-optimistic-insert-debug=#
    系统变量 innodb_limit_optimistic_insert_debug
    范围 全球
    动态
    类型 整数
    默认 0
    最低限度 0
    最大 2**32-1

    限制每个B-Tree页面的记录数量 默认值0意味着没有限制。该选项仅在使用CMake选项编译调试支持时可用 WITH_DEBUG

  • innodb_lock_wait_timeout

    属性
    命令行格式 --innodb-lock-wait-timeout=#
    系统变量 innodb_lock_wait_timeout
    范围 全球,会议
    动态
    类型 整数
    默认 50
    最低限度 1
    最大 1073741824

    在放弃之前InnoDB 事务等待行锁 的时间长度(以秒单位)默认值是50秒。尝试访问由另一个InnoDB事务锁定的行的 事务在发出以下错误之前至多等待对该行的写访问权限:

    错误1205(HY000):超出锁定等待超时; 尝试重新启动事务
    

    当发生锁定等待超时时,当前语句被 回滚(而不是整个事务)。要使整个事务回滚,请使用该--innodb_rollback_on_timeout 选项启动服务器 另请参见第14.21.4节“InnoDB错误处理”

    对于高度交互式应用程序或OLTP系统,您可能会降低此值,以便快速显示用户反馈,或将更新放入队列以供日后处理。您可以为长时间运行的后端操作增加此值,例如数据仓库中的变换步骤,该步骤等待其他大型插入或更新操作完成。

    innodb_lock_wait_timeout仅适用于 InnoDB行锁。MySQL 表锁不会在内部发生,InnoDB并且此超时不适用于等待表锁。

    锁定等待超时值不适用于 启用时的 死锁innodb_deadlock_detect(默认值),因为它InnoDB 会立即检测到死锁并回滚其中一个死锁的事务。何时 innodb_deadlock_detect禁用,发生死锁时InnoDB依赖于 innodb_lock_wait_timeout事务回滚。请参见 第14.5.5.2节“死锁检测和回滚”

    innodb_lock_wait_timeout可以在运行时用SET GLOBALor SET SESSION语句来设置更改 GLOBAL设置需要 SUPER特权并影响后续连接的所有客户端的操作。任何客户端都可以更改SESSION设置 innodb_lock_wait_timeout,仅影响该客户端。

  • innodb_locks_unsafe_for_binlog

    属性
    命令行格式 --innodb-locks-unsafe-for-binlog
    弃用
    系统变量 innodb_locks_unsafe_for_binlog
    范围 全球
    动态 没有
    类型 布尔
    默认 OFF

    此变量影响如何在搜索和索引扫描中InnoDB使用 间隙锁定innodb_locks_unsafe_for_binlog已被弃用,并将在未来的MySQL版本中被删除。

    通常,InnoDB使用称为下一个键锁定的算法该算法结合了索引行锁定和 间隙锁定InnoDB以这样的方式执行行级锁定,即当它搜索或扫描表索引时,它会在遇到的索引记录上设置共享锁或排它锁。因此,行级锁实际上是索引记录锁。另外,索引记录上的下一个键锁也会影响索引记录之前的间隔。也就是说,下一个键锁定是索引记录锁定,并在索引记录之前的间隔上加上间隙锁定。如果一个会话有记录的共享或排他锁R在索引中,另一个会话不能R在索引顺序中立即在间隙中插入新的索引记录 请参见 第14.5.1节“InnoDB锁定”

    默认情况下,值为 innodb_locks_unsafe_for_binlog0(禁用),这意味着启用间隙锁定: InnoDB对搜索和索引扫描使用下一个键锁。要启用该变量,请将其设置为1.这会导致禁用间隙锁定:InnoDB仅对索引扫描和索引扫描使用索引记录锁定。

    启用innodb_locks_unsafe_for_binlog 不会禁用对外键约束检查或重复键检查使用间隙锁定。

    启用的效果 innodb_locks_unsafe_for_binlog与设置事务隔离级别相同 READ COMMITTED,但有以下例外:

    • 启用 innodb_locks_unsafe_for_binlog 是一个全局设置,会影响所有会话,而隔离级别可以全局设置为所有会话,也可以单独设置每个会话。

    • innodb_locks_unsafe_for_binlog 只能在服务器启动时设置,而隔离级别可以在启动时设置或在运行时更改。

    READ COMMITTED因此提供更好,更灵活的控制 innodb_locks_unsafe_for_binlog有关隔离级别对间隙锁定的影响的更多信息,请参见 第14.5.2.1节“事务隔离级别”

    启用innodb_locks_unsafe_for_binlog可能会导致幻影问题,因为其他会话可以在禁用间隙锁定时将新行插入到间隙中。假设id上有一个索引,child并且您希望读取并锁定标识符值大于100的表中的所有行,并打算稍后更新所选行中的某一列:

    SELECT * FROM child WHERE id> 100 FOR UPDATE;
    

    查询从id大于100 的第一条记录开始扫描索引。如果在该范围内的索引记录上设置的锁不锁定在间隔中进行的插入,则另一个会话可以向表中插入新行。因此,如果您要在同SELECT一个事务中再次执行 相同的事务,则会在查询返回的结果集中看到新行。这也意味着如果新项目添加到数据库中,InnoDB不保证可串行化。因此,如果 innodb_locks_unsafe_for_binlog启用,则 InnoDB至多保证隔离级别为READ COMMITTED(冲突序列化仍然有保证。)有关幻影的更多信息,请参见 第14.5.4节“幻影行”

    启用innodb_locks_unsafe_for_binlog具有附加效果:

    • 对于UPDATEDELETE语句, InnoDB仅锁定更新或删除的行。在MySQL评估WHERE条件之后,释放不匹配行的记录锁 这大大降低了死锁的可能性,但它们仍然可能发生。

    • 对于UPDATE语句,如果某行已被锁定,则InnoDB执行半连续读取,将最新的已提交版本返回给MySQL,以便MySQL可以确定该行是否与该WHERE条件 匹配 UPDATE如果行匹配(必须更新),MySQL会再次读取该行,并且这次 InnoDB会锁定它或等待锁定。

    考虑下面的例子,从这个表开始:

    CREATE TABLE t(INT NOT NULL,b INT)ENGINE = InnoDB;
    插入t值(1,2),(2,3),(3,2),(4,3),(5,2);
    承诺;
    

    在这种情况下,表没有索引,因此搜索和索引扫描使用隐藏的聚簇索引进行记录锁定(请参见 第14.8.2.1节“聚簇索引和次索引”)。

    假设一个客户UPDATE使用这些语句执行

    SET autocommit = 0;
    UPDATE t SET b = 5 WHERE b = 3;
    

    假设第二个客户端 UPDATE通过执行第一个客户端的语句来执行这些语句:

    SET autocommit = 0;
    UPDATE t SET b = 4 WHERE b = 2;
    

    由于InnoDB每个执行 UPDATE时,它首先获取用于各行的排他锁,然后确定是否对其进行修改。如果InnoDB不修改该行并被innodb_locks_unsafe_for_binlog启用,则释放该锁。否则, InnoDB保留锁直到交易结束。这会影响事务处理,如下所示。

    如果innodb_locks_unsafe_for_binlog被禁用,第一个UPDATE 获取x锁并且不释放它们中的任何一个:

    X锁(1,2); 保留x锁
    X锁(2,3); 更新(2,3)至(2,5); 保留x锁
    X锁(3,2); 保留x锁
    X锁(4,3); 更新(4,3)至(4,5); 保留x锁
    X锁(5,2); 保留x锁
    

    第二UPDATE块试图获取任何锁(因为第一个更新保留了所有行的锁),并且在第一次UPDATE提交或回退之前不会继续

    X锁(1,2); 阻止并等待第一个UPDATE提交或回滚
    

    如果innodb_locks_unsafe_for_binlog启用,第一个UPDATE 获取x锁并释放那些不修改的行:

    X锁(1,2); 解锁(1,2)
    X锁(2,3); 更新(2,3)至(2,5); 保留x锁
    X锁(3,2); 解锁(3,2)
    X锁(4,3); 更新(4,3)至(4,5); 保留x锁
    X锁(5,2); 解锁(5,2)
    

    对于第二个UPDATEInnoDB执行 半连续读取,将每行的最新提交版本返回给MySQL,以便MySQL可以确定该行是否与以下WHERE 条件匹配UPDATE

    X锁(1,2); 更新(1,2)至(1,4); 保留x锁
    X锁(2,3); 解锁(2,3)
    X锁(3,2); 更新(3,2)至(3,4); 保留x锁
    X锁(4,3); 解锁(4,3)
    X锁(5,2); 更新(5,2)至(5,4); 保留x锁
    
  • innodb_log_buffer_size

    属性
    命令行格式 --innodb-log-buffer-size=#
    系统变量 innodb_log_buffer_size
    范围 全球
    动态 没有
    类型 整数
    默认(> = 5.7.6) 16777216
    默认(<= 5.7.5) 8388608
    最小(> = 5.7.6) 1048576
    最小(<= 5.7.5) 262144
    最大 4294967295

    InnoDB 用于写入磁盘上日志文件 的缓冲区的大小(以字节为单位)引入32k和64k innodb_page_size值后,默认值从8MB变为16MB 一个大的日志缓冲区 允许大 事务运行,而无需在事务提交之前将日志写入磁盘因此,如果您有更新,插入或删除多行的事务,则使日志缓冲区更大可节省磁盘I / O。有关相关信息,请参阅 InnoDB内存配置,以及 第8.5.4节“优化InnoDB重做日志记录”有关通用I / O优化建议,请参见第8.5.8节“优化InnoDB磁盘I / O”

  • innodb_log_checksum_algorithm

    属性
    命令行格式 --innodb-log-checksum-algorithm=#
    介绍 5.7.8
    删除 5.7.9
    系统变量 innodb_log_checksum_algorithm
    范围 全球
    动态
    类型(> = 5.7.8) 列举
    默认(> = 5.7.8) innodb
    有效值(> = 5.7.8)

    innodb

    crc32

    none

    strict_innodb

    strict_crc32

    strict_none

    该配置选项已被删除并被替换 innodb_log_checksums

    指定如何生成并验证存储在每个重做日志磁盘块中校验和innodb_log_checksum_algorithm支持相同的算法innodb_checksum_algorithm以前,只有innodb算法支持重做日志磁盘块。 innodb_log_checksum_algorithm=innodb是默认设置。

    严格的表单一样innodbcrc32none,只是InnoDB暂停,如果遇到校验和值在同一重做日志的组合。您只能在全新的实例中使用严格的设置。严格的设置有点快,因为它们不需要计算新的和旧的校验和值来在磁盘读取期间同时接受这两个值。

    下表显示了之间的区别 noneinnodbcrc32选项值,和他们同行的严格。noneinnodb并将crc32指定类型的校验和值写入每个数据块,但为了兼容性,在读取操作期间验证块时接受任何其他校验和值。每个选项的严格形式只能识别一种校验和,这使得验证更快,但要求InnoDB实例中的所有 重做日志都是在相同的innodb_log_checksum_algorithm下创建的

    表14.15 innodb_log_checksum_algorithm设置

    生成的校验和(写入时) 允许的校验和(阅读时)
    没有 一个常数。 任何校验的产生通过noneinnodbcrc32
    InnoDB的 用软件计算校验和,使用原始算法 InnoDB 任何校验的产生通过noneinnodbcrc32
    CRC32 使用该crc32算法计算校验和,可能使用硬件辅助。 任何校验的产生通过noneinnodbcrc32
    strict_none 一个常数 只有生成的校验和none
    strict_innodb 用软件计算校验和,使用原始算法 InnoDB 只有生成的校验和innodb
    strict_crc32 使用该crc32算法计算校验和,可能使用硬件辅助。 只有生成的校验和crc32

  • innodb_log_checksums

    属性
    命令行格式 --innodb-log-checksums=#
    介绍 5.7.9
    系统变量 innodb_log_checksums
    范围 全球
    动态
    类型 布尔
    默认 ON

    启用或禁用重做日志页面的校验和。 innodb_log_checksums替换 innodb_log_checksum_algorithm

    innodb_log_checksums=ON启用CRC-32C重做日志页面校验和算法。innodb_log_checksums禁用时,重做日志页面校验和字段的内容将被忽略。

    重做日志标题页和重做日志检查点页面上的校验和从不禁用。

  • innodb_log_compressed_pages

    属性
    命令行格式 --innodb-log-compressed-pages=#
    系统变量 innodb_log_compressed_pages
    范围 全球
    动态
    类型 布尔
    默认 ON

    指定是否将重新压缩的 页面的图像 写入 重做日志对压缩数据进行更改时可能会发生重新压缩。

    innodb_log_compressed_pages默认情况下启用,以防止zlib在恢复期间使用不同版本的压缩算法时可能发生的损坏如果您确定 zlib版本不会更改,则可以禁用innodb_log_compressed_pages以减少修改压缩数据的工作负载的重做日志生成。

    要度量启用或禁用的效果 innodb_log_compressed_pages,请比较相同工作负载下两个设置的重做日志生成。测量重做日志生成的选项包括观察输出部分中 Log sequence number(LSN) ,或监视 写入重做日志文件的字节数的状态。 LOGSHOW ENGINE INNODB STATUSInnodb_os_log_written

    有关相关信息,请参见 第14.9.1.6节“OLTP工作负载的压缩”

  • innodb_log_file_size

    属性
    命令行格式 --innodb-log-file-size=#
    系统变量 innodb_log_file_size
    范围 全球
    动态 没有
    类型 整数
    默认 50331648
    最低(> = 5.7.11) 4194304
    最小(<= 5.7.10) 1048576
    最大 512GB / innodb_log_files_in_group

    在每个字节大小日志文件日志组日志文件(innodb_log_file_size* innodb_log_files_in_group的组合大小不能超过略小于512GB的最大值。例如,一对255 GB的日志文件接近极限,但不超过它。默认值是48MB。

    通常,日志文件的组合大小应该足够大,以便服务器可以消除工作负载活动中的高峰和低谷,这通常意味着有足够的重做日志空间来处理一个多小时的写入活动。值越大,缓冲池中所需的检查点刷新活动就越少,从而节省磁盘I / O。较大的日志文件也会使崩溃恢复速度变慢,尽管对MySQL 5.5和更高版本中的恢复性能的改进使得日志文件的大小更小。

    innodb_log_file_sizeMySQL 5.7.11中 的最小值从1MB增加到4MB。

    相关信息请参见 InnoDB日志文件配置有关通用I / O优化建议,请参见 第8.5.8节“优化InnoDB磁盘I / O”

  • innodb_log_files_in_group

    属性
    命令行格式 --innodb-log-files-in-group=#
    系统变量 innodb_log_files_in_group
    范围 全球
    动态 没有
    类型 整数
    默认 2
    最低限度 2
    最大 100

    日志文件日志组InnoDB以循环方式写入文件。默认(推荐)值是2.文件的位置由<文件名>指定 innodb_log_group_home_dir日志文件(innodb_log_file_size* innodb_log_files_in_group的组合大小可以高达512GB。

    相关信息请参见 InnoDB日志文件配置

  • innodb_log_group_home_dir

    属性
    命令行格式 --innodb-log-group-home-dir=dir_name
    系统变量 innodb_log_group_home_dir
    范围 全球
    动态 没有
    类型 目录名称

    InnoDB 重做日志文件 的目录路径,其编号由指定 innodb_log_files_in_group如果你没有指定任何InnoDB日志变量,默认是在MySQL数据目录中创建两个名为ib_logfile0和的 文件 ib_logfile1日志文件大小由innodb_log_file_size系统变量给出

    相关信息请参见 InnoDB日志文件配置

  • innodb_log_write_ahead_size

    属性
    命令行格式 --innodb-log-write-ahead-size=#
    介绍 5.7.4
    系统变量 innodb_log_write_ahead_size
    范围 全球
    动态
    类型 整数
    默认 8192
    最低限度 512 (log file block size)
    最大 Equal to innodb_page_size

    重做日志的预写块大小,以字节为单位。要避免读写,请设置 innodb_log_write_ahead_size为与操作系统或文件系统缓存块大小相匹配。由于重做日志的预写块大小与操作系统或文件系统高速缓存块大小之间的不匹配,重做日志块未完全缓存到操作系统或文件系统时发生了写入时读写。

    有效值 innodb_log_write_ahead_sizeInnoDB日志文件块大小的倍数(2 ^ n)。最小值是InnoDB日志文件块大小(512)。指定最小值时不发生预写。最大值等于 innodb_page_size如果您指定的值 innodb_log_write_ahead_size大于该innodb_page_size 值,则该innodb_log_write_ahead_size 值将被截断为该 innodb_page_size值。

    innodb_log_write_ahead_size 操作系统或文件系统缓存块大小设置得太低会导致 读写fsync由于一次写入多个块,因此将该值设置得过高可能会对日志文件写入的性能产生轻微影响

  • innodb_lru_scan_depth

    属性
    命令行格式 --innodb-lru-scan-depth=#
    系统变量 innodb_lru_scan_depth
    范围 全球
    动态
    类型(64位平台) 整数
    类型(32位平台) 整数
    默认(64位平台) 1024
    默认(32位平台) 1024
    最低(64位平台) 100
    最低(32位平台) 100
    最大(64位平台) 2**64-1
    最大(32位平台) 2**32-1

    影响缓冲池刷新操作 的算法和启发式的参数性能专家主要关注调整I / O密集型工作负载。它指定每个缓冲池实例在缓冲池LRU页面列表中多少,页面清理器线程扫描寻找要刷新的脏页面这是每秒执行一次的后台操作。 InnoDB

    小于默认值的设置通常适用于大多数工作负载。比所需值高得多的值可能会影响性能。只有在典型工作负载下具有空闲I / O容量的情况下才考虑增加此值。相反,如果写密集型工作负载使您的I / O容量达到饱和,请降低该值,尤其是在大型缓冲池的情况下。

    调整时innodb_lru_scan_depth,从低值开始,向上配置设置,目标很少看到零空闲页面。此外,请考虑调整innodb_lru_scan_depth更改缓冲池实例的数量,因为 innodb_lru_scan_depth* innodb_buffer_pool_instances 定义页面清理器线程每秒执行的工作量。

    有关相关信息,请参见 第14.6.3.7节“微调InnoDB缓冲池刷新”有关通用I / O优化建议,请参见 第8.5.8节“优化InnoDB磁盘I / O”

  • innodb_max_dirty_pages_pct

    属性
    命令行格式 --innodb-max-dirty-pages-pct=#
    系统变量 innodb_max_dirty_pages_pct
    范围 全球
    动态
    类型 数字
    默认 75
    最低限度 0
    最大(> = 5.7.5) 99.99
    最大(<= 5.7.4) 99

    InnoDB尝试 缓冲池中清除数据, 以便脏页面的百分比不超过此值。默认值是75。

    innodb_max_dirty_pages_pct 设置确定了冲洗活动的目标。它不会影响冲洗的速度。有关管理刷新速率的信息,请参见第14.6.3.6节“配置InnoDB缓冲池刷新

    有关相关信息,请参见 第14.6.3.7节“微调InnoDB缓冲池刷新”有关通用I / O优化建议,请参见 第8.5.8节“优化InnoDB磁盘I / O”

  • innodb_max_dirty_pages_pct_lwm

    属性
    命令行格式 --innodb-max-dirty-pages-pct-lwm=#
    系统变量 innodb_max_dirty_pages_pct_lwm
    范围 全球
    动态
    类型 数字
    默认 0
    最低限度 0
    最大(> = 5.7.5) 99.99
    最大(<= 5.7.4) 99

    定义代表的比例低水位标记 脏页,在其中预冲洗能够控制脏页比例。默认值为0将完全禁用预冲洗行为。有关更多信息,请参见 第14.6.3.7节“微调InnoDB缓冲池刷新”

  • innodb_max_purge_lag

    属性
    命令行格式 --innodb-max-purge-lag=#
    系统变量 innodb_max_purge_lag
    范围 全球
    动态
    类型 整数
    默认 0
    最低限度 0
    最大 4294967295

    定义清除队列的最大长度。默认值0表示没有限制(没有延迟)。

    清除操作滞后INSERT 使用此选项可强制延迟 UPDATEDELETE执行 操作(请参见第14.3节“InnoDB多版本控制”)。

    InnoDB交易系统认为有通过索引记录删除标记事务的列表 UPDATEDELETE操作。列表的长度代表 purge_lag值。如果 purge_lag超过 innodb_max_purge_lagINSERTUPDATE,和 DELETE操作被延迟。

    为防止在purge_lag变得巨大的极端情况下出现过度延迟 ,可以通过设置innodb_max_purge_lag_delay 配置选项来限制延迟 延迟是在清洗批次开始时计算的。

    对于有问题的工作负载,典型设置可能是100万,假设事务很小,只有100个字节大小,并且允许有100MB未清理的 InnoDB表行。

    滞后值显示为InnoDB Monitor输出TRANSACTIONS部分中 的历史列表长度 该示例输出中滞后值为20:

    ------------
    交易
    ------------
    Trx id counter 0 290328385
    清除trx的n:o <0 290315608 undo n:o <0 17
    历史列表长度20
    

    有关通用I / O优化建议,请参见 第8.5.8节“优化InnoDB磁盘I / O”

  • innodb_max_purge_lag_delay

    属性
    命令行格式 --innodb-max-purge-lag-delay=#
    系统变量 innodb_max_purge_lag_delay
    范围 全球
    动态
    类型 整数
    默认 0
    最低限度 0

    指定由innodb_max_purge_lag 配置选项施加的延迟的最大延迟(以微秒为单位) 非零值表示根据公式计算出的延迟时间的上限值 innodb_max_purge_lag默认值为零意味着延迟时间间隔没有上限。

    有关通用I / O优化建议,请参见 第8.5.8节“优化InnoDB磁盘I / O”

  • innodb_max_undo_log_size

    属性
    命令行格式 --innodb-max-undo-log-size=#
    介绍 5.7.5
    系统变量 innodb_max_undo_log_size
    范围 全球
    动态
    类型 整数
    默认 1073741824
    最低限度 10485760
    最大 2**64-1

    定义撤消表空间的阈值大小。如果撤消表空间超过阈值,innodb_undo_log_truncate则启用时可将其标记为截断 默认值是1073741824字节(1024兆字节)。

    有关更多信息,请参见 第14.7.8节“截断撤消表空间”

  • innodb_merge_threshold_set_all_debug

    属性
    命令行格式 --innodb-merge-threshold-set-all-debug=#
    介绍 5.7.6
    系统变量 innodb_merge_threshold_set_all_debug
    范围 全球
    动态
    类型 整数
    默认 50
    最低限度 1
    最大 50

    MERGE_THRESHOLD 为当前位于字典缓存中的所有索引 重写当前设置的索引页定义页面完全百分比值该选项仅在使用CMake选项编译调试支持时可用有关相关信息,请参见 第14.6.13节“为索引页面配置合并阈值”WITH_DEBUG

  • innodb_monitor_disable

    属性
    命令行格式 --innodb-monitor-disable=[counter|module|pattern|all]
    系统变量 innodb_monitor_disable
    范围 全球
    动态
    类型

    禁用InnoDB 度量标准计数器计数器数据可以使用INFORMATION_SCHEMA.INNODB_METRICS查询 有关使用信息,请参见 第14.15.6节“InnoDB INFORMATION_SCHEMA度量标准表”

    innodb_monitor_disable='latch'禁用统计信息收集 SHOW ENGINE INNODB MUTEX有关更多信息,请参见 第13.7.5.15节“SHOW ENGINE语法”

  • innodb_monitor_enable

    属性
    命令行格式 --innodb-monitor-enable=[counter|module|pattern|all]
    系统变量 innodb_monitor_enable
    范围 全球
    动态
    类型

    启用InnoDB 指标计数器计数器数据可以使用INFORMATION_SCHEMA.INNODB_METRICS查询 有关使用信息,请参见 第14.15.6节“InnoDB INFORMATION_SCHEMA度量标准表”

    innodb_monitor_enable='latch'启用统计信息收集 SHOW ENGINE INNODB MUTEX有关更多信息,请参见 第13.7.5.15节“SHOW ENGINE语法”

  • innodb_monitor_reset

    属性
    命令行格式 --innodb-monitor-reset=[counter|module|pattern|all]
    系统变量 innodb_monitor_reset
    范围 全球
    动态
    类型

    InnoDB 度量指标计数器 的计数值重置 为零。计数器数据可以使用INFORMATION_SCHEMA.INNODB_METRICS查询 有关使用信息,请参见 第14.15.6节“InnoDB INFORMATION_SCHEMA度量标准表”

    innodb_monitor_reset='latch'重置报告的统计数据 SHOW ENGINE INNODB MUTEX有关更多信息,请参见 第13.7.5.15节“SHOW ENGINE语法”

  • innodb_monitor_reset_all

    属性
    命令行格式 --innodb-monitor-reset-all=[counter|module|pattern|all]
    系统变量 innodb_monitor_reset_all
    范围 全球
    动态
    类型

    重置InnoDB 指标计数器的所有值(最小值,最大值等) 计数器数据可以使用INFORMATION_SCHEMA.INNODB_METRICS查询 有关使用信息,请参见 第14.15.6节“InnoDB INFORMATION_SCHEMA度量标准表”

  • innodb_numa_interleave

    属性
    命令行格式 --innodb-numa-interleave=#
    介绍 5.7.9
    系统变量 innodb_numa_interleave
    范围 全球
    动态 没有
    类型 布尔
    默认 OFF

    启用NUMA交错存储器策略以分配InnoDB缓冲池。innodb_numa_interleave启用时,NUMA内存策略设置为MPOL_INTERLEAVEmysqld的进程。InnoDB缓冲池分配,在NUMA内存策略设置回MPOL_DEFAULT为了使innodb_numa_interleave选项可用,MySQL必须在启用NUMA的Linux系统上编译。

    从MySQL 5.7.17开始,CMakeWITH_NUMA根据当前平台是否NUMA支持设置默认 有关更多信息,请参见 第2.9.4节“MySQL源配置选项”

  • innodb_old_blocks_pct

    属性
    命令行格式 --innodb-old-blocks-pct=#
    系统变量 innodb_old_blocks_pct
    范围 全球
    动态
    类型 整数
    默认 37
    最低限度 5
    最大 95

    指定用于旧块子列表InnoDB 缓冲池的近似百分比 值的范围是5到95.默认值是37(即池的3/8)。通常与组合使用 innodb_old_blocks_time

    有关更多信息,请参见 第14.6.3.4节“使缓冲池抗扫描”有关缓冲池管理, LRU算法和 驱逐策略的信息,请参见 第14.6.3.1节“InnoDB缓冲池”

  • innodb_old_blocks_time

    属性
    命令行格式 --innodb-old-blocks-time=#
    系统变量 innodb_old_blocks_time
    范围 全球
    动态
    类型 整数
    默认 1000
    最低限度 0
    最大 2**32-1

    非零值可防止 缓冲池由仅在短时间内引用的数据填充,例如在全表扫描期间增加此值可以防止全表扫描干扰缓存池中缓存的数据。

    指定插入旧子列表的块在其第一次访问后必须保留多长时间(以毫秒为单位),然后才能将其移至新子列表。如果值为0,则插入旧子列表的块将在第一次访问时立即移动到新子列表中,无论插入后多久发生访问。如果该值大于0,则块会保留在旧的子列表中,直到第一次访问之后至少发生数毫秒的访问为止。例如,值为1000会导致块在第一次访问后停留在旧子列表中1秒钟,然后才有资格移动到新子列表。

    缺省值是1000。

    这个配置选项通常与其结合使用 innodb_old_blocks_pct有关更多信息,请参见 第14.6.3.4节“使缓冲池抗扫描”有关缓冲池管理, LRU算法和 驱逐策略的信息,请参见 第14.6.3.1节“InnoDB缓冲池”

  • innodb_online_alter_log_max_size

    属性
    命令行格式 --innodb-online-alter-log-max-size=#
    系统变量 innodb_online_alter_log_max_size
    范围 全球
    动态
    类型 整数
    默认 134217728
    最低限度 65536
    最大 2**64-1

    指定表的联机DDL操作期间使用的临时日志文件大小的上限(以字节为单位)InnoDB对于正在创建的每个索引或正在更改的表,都有一个这样的日志文件。该日志文件存储在DDL操作期间插入,更新或删除的表中的数据。当需要时,临时日志文件将被扩展 innodb_sort_buffer_size,直到达到最大值 innodb_online_alter_log_max_size如果临时日志文件超过了大小上限,则 ALTER TABLE操作失败,所有未提交的并发DML操作都会回滚。因此,此选项的较大值允许在联机DDL操作期间发生更多DML,但是也可以延长DDL操作结束时的时间间隔,以便锁定表以应用日志中的数据。

  • innodb_open_files

    属性
    命令行格式 --innodb-open-files=#
    系统变量 innodb_open_files
    范围 全球
    动态 没有
    类型 整数
    默认 -1 (autosized)
    最低限度 10
    最大 4294967295

    只有使用多个InnoDB 表空间时,此配置选项才是相关的 它指定了MySQL一次可以保持打开的最大.ibd 文件数量 最小值为10.如果innodb_file_per_table未启用,则默认值为300 ,而较高值为300, table_open_cache否则为。

    用于文件的文件描述符.ibd用于InnoDB表格。它们独立于--open-files-limit服务器选项指定的那些 ,并且不影响表缓存的操作。有关通用I / O优化建议,请参见 第8.5.8节“优化InnoDB磁盘I / O”

  • innodb_optimize_fulltext_only

    属性
    命令行格式 --innodb-optimize-fulltext-only=#
    系统变量 innodb_optimize_fulltext_only
    范围 全球
    动态
    类型 布尔
    默认 OFF

    改变表格的OPTIMIZE TABLE 操作方式InnoDB打算在InnoDB具有FULLTEXT索引的表的 维护操作期间暂时启用

    默认情况下,OPTIMIZE TABLE 重新组织中的聚集索引中的数据 启用此选项时, OPTIMIZE TABLE跳过表数据的重新组织,而是处理InnoDB FULLTEXT索引的新添加,删除和更新的标记数据 有关更多信息,请参阅 优化InnoDB全文索引

  • innodb_optimize_point_storage

    属性
    命令行格式 --innodb-optimize-point-storage=#
    介绍 5.7.5
    删除 5.7.6
    系统变量 innodb_optimize_point_storage
    范围 会议
    动态
    类型 布尔
    默认 OFF

    在创建一个类型的列之前启用此变量, POINT以将POINT 数据类型内部存储为可变长度 BLOB数据。

  • innodb_page_cleaners

    属性
    命令行格式 --innodb-page-cleaners=#
    介绍 5.7.4
    系统变量 innodb_page_cleaners
    范围 全球
    动态 没有
    类型 整数
    默认(> = 5.7.8) 4
    默认(<= 5.7.7) 1
    最低限度 1
    最大 64

    从缓冲池实例中刷新脏页的页面清理器线程的数量。页面清理器线程执行清空列表和LRU刷新。在MySQL 5.6中引入了单页面清理器线程,以便从InnoDB主线程卸载缓冲池清除工作在MySQL 5.7中,InnoDB为多个页面清理器线程提供支持。值为1的维护MySQL 5.7之前的配置,其中有一个页面清理器线程。当存在多个页面清理器线程时,将为每个缓冲池实例分配缓冲池清理任务给闲置的页面清理器线程。innodb_page_cleanersMySQL 5.7中默认值从1改为4。如果页面清理线程的数量超过缓冲池实例的数量,innodb_page_cleaners 则会自动设置为与 innodb_buffer_pool_instances

    如果在将缓冲池实例中的脏页面刷新到数据文件时,您的工作负载被写入IO界限,并且系统硬件具有可用容量,则增加页面清理器线程数可能有助于提高写入IO吞吐量。

    多线程页面清理器支持扩展到MySQL 5.7中的关闭和恢复阶段。

    setpriority()系统调用是用来在那里它被支持的Linux平台,并且其中 的mysqld执行用户被授权给 page_cleaner线程优先于其他MySQL和InnoDB线程帮助页面刷新保持与当前工作负载的速度。 setpriority()支持由此InnoDB启动消息指示

    [注意] InnoDB:如果mysqld执行用户被授权,页面清理
    线程优先级可以改变。请参阅setpriority()的手册页。        
    

    对于不由systemd管理服务器启动和关闭的系统,可以在中配置mysqld执行用户授权 /etc/security/limits.conf例如,如果mysqldmysql用户下运行 ,则可以mysql通过将这些行添加到以下来授权 用户 /etc/security/limits.conf

    mysql很难很好-20
    mysql软很好-20
    

    对于systemd受管系统,通过LimitNICE=-20在本地化系统配置文件中指定可以实现相同的目的例如,创建一个名为override.confin 的文件 /etc/systemd/system/mysqld.service.d/override.conf 并添加此条目:

    [服务]
    LimitNICE = -20
    

    创建或更改后override.conf,重新加载systemd配置,然后告诉systemd重新启动MySQL服务:

    systemctl守护进程重新加载
    systemctl restart mysqld#RPM平台
    systemctl重启mysql#Debian平台
    

    有关使用本地化systemd配置文件的更多信息,请参阅 配置systemd for MySQL

    授权mysqld执行用户后,使用cat命令验证Nicemysqld进程配置的限制

    shell> cat / proc / mysqld_pid/ limits | grep很好
    最大不错的优先级18446744073709551596 18446744073709551596 
    
  • innodb_page_size

    属性
    命令行格式 --innodb-page-size=#k
    系统变量 innodb_page_size
    范围 全球
    动态 没有
    类型 列举
    默认 16384
    有效值(> = 5.7.6)

    4k

    8k

    16k

    32k

    64k

    4096

    8192

    16384

    32768

    65536

    有效值(<= 5.7.5)

    4k

    8k

    16k

    4096

    8192

    16384

    指定MySQL 实例中 所有表空间页面大小您可以使用值64k,32k (默认值),或者 来指定页面大小或者,您可以以字节为单位指定页面大小(65536,32768,16384,8192,4096)。 InnoDB 16k8k4k

    innodb_page_size只能在初始化MySQL实例之前进行配置,之后不能更改。如果未指定值,则使用默认页面大小初始化实例。请参见 第14.6.1节“InnoDB启动配置”

    在MySQL 5.7中增加了对32k和64k页面大小的支持。对于32k和64k页面大小,最大行长度大约为16000字节。 ROW_FORMAT=COMPRESSEDinnodb_page_size设置为32KB或64KB 时不受支持 因为innodb_page_size=32k,范围的大小是2MB。因为innodb_page_size=64k,范围大小是4MB。 innodb_log_buffer_size在使用32k或64k页面大小时应该设置为至少16M(默认值)。

    默认的16KB页面大小或更大适用于各种工作负载,特别是涉及涉及批量更新的表扫描和DML操作的查询。对于 涉及许多小写入的OLTP工作负载,较小的页面大小可能更有效,其中当单个页面包含许多行时,争用可能成为问题。较小的页面对于SSD存储设备也可能是有效的, SSD存储设备通常使用小块大小。保持 InnoDB页面大小接近存储设备块大小可将重写到磁盘的未更改数据量减至最少。

    第一个系统表空间数据文件(ibdata1的最小文件大小因innodb_page_size值而有关innodb_data_file_path 更多信息,请参阅选项说明。

    有关通用I / O优化建议,请参见 第8.5.8节“优化InnoDB磁盘I / O”

  • innodb_print_all_deadlocks

    属性
    命令行格式 --innodb-print-all-deadlocks=#
    系统变量 innodb_print_all_deadlocks
    范围 全球
    动态
    类型 布尔
    默认 OFF

    当启用该选项,所有信息 死锁InnoDB用户交易被记录在 mysqld 错误日志否则,只能使用该SHOW ENGINE INNODB STATUS命令查看有关最后一个死锁的信息偶尔的 InnoDB僵局并不一定是个问题,因为InnoDB立即检测到状况并自动回滚其中一项交易。如果应用程序没有适当的错误处理逻辑来检测回滚并重试其操作,则可以使用此选项来排查为什么发生死锁。大量的死锁可能表示需要重构发布DML的事务 SELECT ... FOR UPDATE多个表的语句,以便每个事务以相同的顺序访问表,从而避免死锁状况。

    有关相关信息,请参见 第14.5.5节“InnoDB中的死锁”

  • innodb_purge_batch_size

    属性
    命令行格式 --innodb-purge-batch-size=#
    系统变量 innodb_purge_batch_size
    范围 全球
    动态
    类型 整数
    默认 300
    最低限度 1
    最大 5000

    定义从历史列表中清除一个批次中解析和处理的撤消日志页面的数量 在多线程吹扫的配置中,协调器净化线程分割innodb_purge_batch_size通过 innodb_purge_threads并分配该数量的页的每个吹扫线程。innodb_purge_batch_size选项还定义了在通过撤消日志每128次迭代后清除释放的撤消日志页的数量。

    innodb_purge_batch_size选件适用于结合innodb_purge_threads 设置进行高级性能调整大多数MySQL用户不需要改变 innodb_purge_batch_size默认值。

    有关相关信息,请参见 第14.6.11节“配置InnoDB清除调度”

  • innodb_purge_threads

    属性
    命令行格式 --innodb-purge-threads=#
    系统变量 innodb_purge_threads
    范围 全球
    动态 没有
    类型 整数
    默认(> = 5.7.8) 4
    默认(<= 5.7.7) 1
    最低限度 1
    最大 32

    专门用于InnoDB 清除操作的后台线程的数量 最小值为1表示清除操作总是由后台线程执行,而不是主线程的一部分 在一个或多个后台线程中运行清除操作有助于减少内部争用 InnoDB,提高可伸缩性。将该值增加到大于1会产生许多单独的清除线程,这可以提高在多个表上执行DML操作的系统的效率 最大值是32。

    有关相关信息,请参见 第14.6.11节“配置InnoDB清除调度”

  • innodb_purge_rseg_truncate_frequency

    属性
    命令行格式 --innodb-purge-rseg-truncate-frequency=#
    介绍 5.7.5
    系统变量 innodb_purge_rseg_truncate_frequency
    范围 全球
    动态
    类型 整数
    默认 128
    最低限度 1
    最大 128

    定义清除系统根据调用清除的次数释放回滚段的频率。撤消表空间不能被截断,直到其回退段被释放。通常情况下,清除系统每调用一次清除128次就释放一次回滚段。默认值为128.减小此值将增加清除线程释放回滚段的频率。

    innodb_purge_rseg_truncate_frequency旨在用于 innodb_undo_log_truncate有关更多信息,请参见 第14.7.8节“截断撤消表空间”

  • innodb_random_read_ahead

    属性
    命令行格式 --innodb-random-read-ahead=#
    系统变量 innodb_random_read_ahead
    范围 全球
    动态
    类型 布尔
    默认 OFF

    启用随机 预读技术来优化InnoDBI / O。

    有关不同类型的预读请求的性能注意事项的详细信息,请参见 第14.6.3.5节“配置InnoDB缓冲池预取(预读)”有关通用I / O优化建议,请参见 第8.5.8节“优化InnoDB磁盘I / O”

  • innodb_read_ahead_threshold

    属性
    命令行格式 --innodb-read-ahead-threshold=#
    系统变量 innodb_read_ahead_threshold
    范围 全球
    动态
    类型 整数
    默认 56
    最低限度 0
    最大 64

    控制线性的灵敏度 预读的是 InnoDB使用预取页入 缓冲器池如果 InnoDB至少innodb_read_ahead_threshold从一个范围 (64页)中按顺序读取 页面,它将启动对整个后续范围的异步读取。值的允许范围是0到64.值为0将禁用预读。对于缺省值56, InnoDB必须从一定范围内按顺序读取至少56页,以启动以下范围的异步读取。

    了解通过预读机制来读取多少页面,以及这些页面中有多少从缓冲池中被删除而无需被访问,在微调innodb_read_ahead_threshold 设置时会很有用 SHOW ENGINE INNODB STATUS输出显示对抗来自信息 Innodb_buffer_pool_read_aheadInnodb_buffer_pool_read_ahead_evicted 全局状态变量,其报告的页数带入缓冲池的预读请求,以及这些页面的数量驱逐分别从缓冲池而没有被访问。状态变量报告自上次服务器重新启动以来的全局值。

    SHOW ENGINE INNODB STATUS还显示了读取预读页面的速率以及这些页面被驱逐而未被访问的速率。每秒平均值基于自上次调用以来收集的统计信息,SHOW ENGINE INNODB STATUS并显示在输出BUFFER POOL AND MEMORY 部分中 SHOW ENGINE INNODB STATUS

    有关更多信息,请参见 第14.6.3.5节“配置InnoDB缓冲池预取(预读)”有关通用I / O优化建议,请参见 第8.5.8节“优化InnoDB磁盘I / O”

  • innodb_read_io_threads

    属性
    命令行格式 --innodb-read-io-threads=#
    系统变量 innodb_read_io_threads
    范围 全球
    动态 没有
    类型 整数
    默认 4
    最低限度 1
    最大 64

    用于读取操作的I / O线程数 InnoDB它与写入线程相对应innodb_write_io_threads有关更多信息,请参见 第14.6.7节“配置背景InnoDB I / O线程数”有关通用I / O优化建议,请参见 第8.5.8节“优化InnoDB磁盘I / O”

    注意

    在Linux系统上运行多个MySQL服务器(通常超过12)与默认设置 innodb_read_io_threadsinnodb_write_io_threads以及Linux的aio-max-nr设置可以超过系统限制。理想情况下,增加 aio-max-nr设置; 作为一种解决方法,您可以减少一个或两个MySQL配置选项的设置。

  • innodb_read_only

    属性
    命令行格式 --innodb-read-only=#
    系统变量 innodb_read_only
    范围 全球
    动态 没有
    类型 布尔
    默认 OFF

    InnoDB以只读模式 启动用于在只读介质上分发数据库应用程序或数据集。也可以用于数据仓库以在多个实例之间共享相同的数据目录。有关更多信息,请参见第14.6.2节“将InnoDB配置为只读操作”

  • innodb_replication_delay

    属性
    命令行格式 --innodb-replication-delay=#
    系统变量 innodb_replication_delay
    范围 全球
    动态
    类型 整数
    默认 0
    最低限度 0
    最大 4294967295

    如果innodb_thread_concurrency 达到从属服务器上的复制线程延迟(以毫秒为单位)

  • innodb_rollback_on_timeout

    属性
    命令行格式 --innodb-rollback-on-timeout
    系统变量 innodb_rollback_on_timeout
    范围 全球
    动态 没有
    类型 布尔
    默认 OFF

    InnoDB 默认情况下,仅回滚事务超时的最后一条语句。如果 --innodb_rollback_on_timeout指定,则事务超时会导致 InnoDB中止并回滚整个事务。

    注意

    如果启动事务语句是 START TRANSACTIONBEGIN 语句,则回滚不会取消该语句。进一步的SQL语句成为交易的一部分,直到发生COMMITROLLBACK或某些SQL语句导致隐式提交。

    有关更多信息,请参见 第14.21.4节“InnoDB错误处理”

  • innodb_rollback_segments

    属性
    命令行格式 --innodb-rollback-segments=#
    系统变量 innodb_rollback_segments
    范围 全球
    动态
    类型 整数
    默认 128
    最低限度 1
    最大 128

    定义回滚段的数量 由使用InnoDB

    一个回滚段始终分配给系统表空间,并且32个回滚段保留供临时表使用,并驻留在临时表空间(ibtmp1)中。要为生成撤消记录的数据修改事务分配额外的回滚段, innodb_rollback_segments必须将其设置为大于33的值。如果配置单独的撤消表空间,系统表空间中的回滚段将呈现为非活动状态。每个回滚段最多可以支持1023个数据修改事务。

    innodb_rollback_segments 设定为32以下时,InnoDB小时将一个回滚段分配给系统表空间,将32分配给临时表空间(ibtmp1)。

    innodb_rollback_segments 设置为大于32的值时,InnoDB 将一个回滚段分配给系统表空间,将32分配给临时表空间(ibtmp1)和其他回滚段以撤消表空间(如果存在)。如果撤消表空间不存在,则将额外的回滚段分配给系统表空间。

    尽管您可以增加或减少使用的回滚段InnoDB的数量,但系统中物理存在的回滚段的数量不会减少。因此,您可能从此参数的值较低开始逐渐增加值,以避免分配不需要的回滚段。innodb_rollback_segments 默认值是128,这也是最大值。

    有关回滚段的更多信息,请参见 第14.3节“InnoDB多版本控制”有关配置单独的撤消表空间的信息,请参见 第14.7.7节“配置撤消表空间”

  • innodb_saved_page_number_debug

    属性
    命令行格式 --innodb-saved-page-number-debug=#
    系统变量 innodb_saved_page_number_debug
    范围 全球
    动态
    类型 整数
    默认 0
    最大 2**23-1

    保存页码。设置 innodb_fil_make_page_dirty_debug 选项会污染页面定义的页面 innodb_saved_page_number_debuginnodb_saved_page_number_debug选项仅在使用CMake选项编译调试支持时可用 WITH_DEBUG

  • innodb_sort_buffer_size

    属性
    命令行格式 --innodb-sort-buffer-size=#
    系统变量 innodb_sort_buffer_size
    范围 全球
    动态 没有
    类型 整数
    默认 1048576
    最低限度 65536
    最大 67108864

    指定用于在创建InnoDB索引期间对数据进行排序的排序缓冲区的大小指定的大小定义了读入内存进行内部排序然后写入磁盘的数据量。这个过程被称为运行在合并阶段,读入并合并指定大小的缓冲区对。设置越大,运行和合并越少。

    此排序区域仅用于创建索引期间的合并排序,而不用于以后的索引维护操作。索引创建完成后缓冲区将被释放。

    此选项的值还控制在线DDL期间临时日志文件被扩展以记录并发DML的数量 操作

    在此设置可配置之前,该大小被硬编码为1048576字节(1MB),这仍然是默认设置。

    创建索引的语句ALTER TABLECREATE TABLE语句中,分配了3个缓冲区,每个缓冲区的大小均由此选项定义。此外,辅助指针被分配给排序缓冲区中的行,以便排序可以在指针上运行(而不是在排序操作期间移动行)。

    对于典型的排序操作,可以使用像这样的公式来估计内存消耗:

    (6 / * FTS_NUM_AUX_INDEX * / *(3 * @@ global.innodb_sort_buffer_size)
    + 2 * number_of_partitions * number_of_secondary_indexes_created
    *(@@ global.innodb_sort_buffer_size / dict_index_get_min_size(index)* /)
    * 8 / * 64位sizeof * buf->元组* /“)
    

    @@global.innodb_sort_buffer_size/dict_index_get_min_size(index) 表示持有的最大元组。2 * (@@global.innodb_sort_buffer_size/*dict_index_get_min_size(index)*/) * 8 /*64-bit size of *buf->tuples*/指示分配的辅助指针。

    注意

    对于32位,乘以4而不是8。

    对于全文索引的并行排序,乘以 innodb_ft_sort_pll_degree 设置:

    (6 / * FTS_NUM_AUX_INDEX * / * @@ global.innodb_ft_sort_pll_degree)
    
  • innodb_spin_wait_delay

    属性
    命令行格式 --innodb-spin-wait-delay=#
    系统变量 innodb_spin_wait_delay
    范围 全球
    动态
    类型(64位平台) 整数
    类型(32位平台) 整数
    默认(64位平台) 6
    默认(32位平台) 6
    最低(64位平台) 0
    最低(32位平台) 0
    最大(64位平台) 2**64-1
    最大(32位平台) 2**32-1

    自旋锁定 轮询之间的最大延迟时间 该机制的低级实现取决于硬件和操作系统的组合,因此延迟不对应于固定的时间间隔。有关更多信息,请参见 第14.6.10节“配置旋转锁定轮询”

  • innodb_stats_auto_recalc

    属性
    命令行格式 --innodb-stats-auto-recalc=#
    系统变量 innodb_stats_auto_recalc
    范围 全球
    动态
    类型 布尔
    默认 ON

    导致表格中的数据发生实质性更改后InnoDB自动重新计算 持久性统计信息阈值是表中行的10%。此设置适用于innodb_stats_persistent 启用选项时创建的表格 自动统计重新计算也可以通过STATS_PERSISTENT=1在a CREATE TABLEALTER TABLE语句中指定进行配置 用于生成统计数据的采样数据量由innodb_stats_persistent_sample_pages 配置选项控制

    有关更多信息,请参见 第14.6.12.1节“配置持久优化器统计参数”

  • innodb_stats_include_delete_marked

    属性
    命令行格式 --innodb-stats-include-delete-marked=#
    介绍 5.7.17
    系统变量 innodb_stats_include_delete_marked
    范围 全球
    动态
    类型 布尔
    默认 OFF

    默认情况下,InnoDB在计算统计信息时读取未提交的数据。如果未提交的事务从表中删除行,则 InnoDB排除在计算行估计和索引统计信息时删除标记的记录,这可能会导致针对在表上操作的其他事务的非最佳执行计划使用事务隔离级别以外的 READ UNCOMMITTED为了避免这种情况, innodb_stats_include_delete_marked 可以启用它来确保InnoDB 在计算持久性优化器统计信息时包含删除标记的记录。

    innodb_stats_include_delete_marked 启用时,ANALYZE TABLE 重新计算统计数据时,会考虑删除标记的记录。

    innodb_stats_include_delete_marked 是影响所有InnoDB的全局设置它仅适用于持久性优化器统计信息。

    有关相关信息,请参见 第14.6.12.1节“配置持久优化器统计参数”

  • innodb_stats_method

    属性
    命令行格式 --innodb-stats-method=name
    系统变量 innodb_stats_method
    范围 全球
    动态
    类型 列举
    默认 nulls_equal
    有效值

    nulls_equal

    nulls_unequal

    nulls_ignored

    NULL在收集 有关表格索引值分布的统计信息 ,服务器如何处理InnoDB允许值是 nulls_equalnulls_unequalnulls_ignored因为 nulls_equal,所有的NULL 索引值都被认为是相等的,并形成一个大小等于NULL数量的单个值组 因为 nulls_unequalNULL 值被认为是不相等的,并且每个 NULL值形成大小为1的不同值组。对于nulls_ignoredNULL值被忽略。

    用于生成表统计信息的方法会影响优化程序如何为查询执行选择索引,如第8.3.7节“InnoDB和MyISAM索引统计信息收集”中所述

  • innodb_stats_on_metadata

    属性
    命令行格式 --innodb-stats-on-metadata
    系统变量 innodb_stats_on_metadata
    范围 全球
    动态
    类型 布尔
    默认 OFF

    此选项仅适用于将优化器 统计信息配置为非持久性的情况。优化器统计信息在innodb_stats_persistent禁用时或者在创建或更改单个表 时不会保留到磁盘 STATS_PERSISTENT=0有关更多信息,请参见第14.6.12.2节“配置非持久性优化器统计参数”

    innodb_stats_on_metadata启用时, InnoDB将更新的非持久性 的统计数据时,元数据语句,如SHOW TABLE STATUS访问时或 INFORMATION_SCHEMA.TABLESINFORMATION_SCHEMA.STATISTICS 表。(这些更新类似于发生的情况 ANALYZE TABLE。)禁用时, InnoDB不会在这些操作期间更新统计信息。保持禁用设置可以提高具有大量表或索引的模式的访问速度。它还可以提高涉及表的查询 执行计划的稳定性 InnoDB

    要更改设置,请发出声明,其中or或(或 or )。更改设置需要特权并立即影响所有连接的操作。 SET GLOBAL innodb_stats_on_metadata=modemodeONOFF10SUPER

  • innodb_stats_persistent

    属性
    命令行格式 --innodb-stats-persistent=setting
    系统变量 innodb_stats_persistent
    范围 全球
    动态
    类型 布尔
    默认 ON
    有效值

    OFF

    ON

    0

    1

    指定是否将InnoDB索引统计信息保存到磁盘。否则,可能会频繁重新计算统计信息,这可能会导致查询执行计划发生变化 创建表时,此设置与每个表一起存储。您可以设置 innodb_stats_persistent在全球范围内创建表之前,或使用 STATS_PERSISTENT的条款 CREATE TABLEALTER TABLE语句覆盖系统级设置并配置各个表的持久性统计信息。

    有关更多信息,请参见 第14.6.12.1节“配置持久优化器统计参数”

  • innodb_stats_persistent_sample_pages

    属性
    命令行格式 --innodb-stats-persistent-sample-pages=#
    系统变量 innodb_stats_persistent_sample_pages
    范围 全球
    动态
    类型 整数
    默认 20

    估计索引列的基数和其他 统计数据时要抽样 的索引页数,例如由 增加该值会提高索引统计信息的准确性,从而可以提高查询执行计划的执行过程中,在增加的I / O的费用表。有关更多信息,请参见第14.6.12.1节“配置持久优化器统计参数”ANALYZE TABLEANALYZE TABLEInnoDB

    注意

    设置较高值 innodb_stats_persistent_sample_pages 可能会导致ANALYZE TABLE执行时间过长要估计访问的数据库页数ANALYZE TABLE,请参见 第14.6.12.3节“估计InnoDB表的ANALYZE TABLE复杂度”

    innodb_stats_persistent_sample_pages仅适用于 innodb_stats_persistent启用了表格的情况; innodb_stats_persistent禁用时,则 innodb_stats_transient_sample_pages 应用。

  • innodb_stats_sample_pages

    属性
    命令行格式 --innodb-stats-sample-pages=#
    弃用
    系统变量 innodb_stats_sample_pages
    范围 全球
    动态
    类型 整数
    默认 8
    最低限度 1
    最大 2**64-1

    已过时。innodb_stats_transient_sample_pages 改为使用

  • innodb_stats_transient_sample_pages

    属性
    命令行格式 --innodb-stats-transient-sample-pages=#
    系统变量 innodb_stats_transient_sample_pages
    范围 全球
    动态
    类型 整数
    默认 8

    估计索引列的基数和其他 统计数据时要抽样 的索引页数,例如由 默认值为8.增加值可以提高索引统计的准确性,这可以改进 查询执行计划,但会增加打开表或重新计算统计信息时的I / O。 有关更多信息,请参见 第14.6.12.2节“配置非持久性优化器统计参数”ANALYZE TABLEInnoDB

    注意

    设置较高值 innodb_stats_transient_sample_pages可能会导致ANALYZE TABLE执行时间过长要估计访问的数据库页数ANALYZE TABLE,请参见 第14.6.12.3节“估计InnoDB表的ANALYZE TABLE复杂度”

    innodb_stats_transient_sample_pages仅适用于 innodb_stats_persistent禁用表格的情况; innodb_stats_persistent启用时, innodb_stats_persistent_sample_pages 则应该被使用。代替 innodb_stats_sample_pages有关更多信息,请参见 第14.6.12.2节“配置非持久性优化器统计参数”

  • innodb_status_output

    属性
    命令行格式 --innodb-status-output
    介绍 5.7.4
    系统变量 innodb_status_output
    范围 全球
    动态
    类型 布尔
    默认 OFF

    启用或禁用标准InnoDB监视器的定期输出 也可以与锁定监视器一起使用 innodb_status_output_locks或禁用周期性输出 InnoDB有关更多信息,请参见第14.17.2节“启用InnoDB监视器”

  • innodb_status_output_locks

    属性
    命令行格式 --innodb-status-output-locks
    介绍 5.7.4
    系统变量 innodb_status_output_locks
    范围 全球
    动态
    类型 布尔
    默认 OFF

    启用或禁用InnoDB锁定监视器。当启用时,InnoDB锁定监视器打印SHOW ENGINE INNODB STATUS输出中的锁定以及打印到MySQL错误日志的周期性输出中的附加信息 InnoDB锁定监视器的周期性输出将作为标准InnoDB 监视器输出的一部分进行打印因此,标准InnoDB监视器必须启用InnoDB 锁定监视器才能定期将数据打印到MySQL错误日志中。有关更多信息,请参见 第14.17.2节“启用InnoDB监视器”

  • innodb_strict_mode

    属性
    命令行格式 --innodb-strict-mode=#
    系统变量 innodb_strict_mode
    范围 全球,会议
    动态
    类型 布尔
    默认(> = 5.7.7) ON
    默认(<= 5.7.6) OFF

    innodb_strict_mode启用时, InnoDB将返回错误,而不是警告了一定的条件。

    严格模式有助于防范SQL中忽略的拼写错误和语法错误,或各种操作模式和SQL语句组合的其他意外后果。innodb_strict_mode启用时, InnoDB提出了在某些情况下错误条件,而不是发出警告和处理指定的声明(也许无意的行为)。这与sql_modeMySQL中的类似 ,它控制MySQL接受的SQL语法,并确定它是静默地忽略错误还是验证输入语法和数据值。

    innodb_strict_mode设置会影响语法错误的处理CREATE TABLEALTER TABLECREATE INDEX,和 OPTIMIZE TABLE语句。 innodb_strict_mode还可以进行记录大小检查,以便记录对于所选页面大小而言过大,从而确保INSERTUPDATE永不失败。

    Oracle建议使 innodb_strict_mode用时 ROW_FORMATKEY_BLOCK_SIZE条款中 CREATE TABLEALTER TABLECREATE INDEX语句。innodb_strict_mode被禁用, InnoDB忽略了相互矛盾的条款且仅在消息日志警告创建表或索引。结果表可能具有与预期不同的特性,例如尝试创建压缩表时缺乏压缩支持。innodb_strict_mode启用时,这些问题产生的直接错误,并且不会创建表或索引。

    您可以innodb_strict_mode在启动mysqld时或在MySQL 配置文件中启用或禁用 命令行您也可以innodb_strict_mode在运行时使用该语句启用或禁用 ,其中或者更改设置需要 特权并影响后续连接的所有客户端的操作。任何客户端都可以更改设置 ,并且该设置仅影响该客户端。 SET [GLOBAL|SESSION] innodb_strict_mode=modemodeONOFFGLOBALSUPERSESSIONinnodb_strict_mode

    innodb_strict_mode不适用于一般的表空间通用表空间的表空间管理规则是独立于,严格执行的 innodb_strict_mode有关更多信息,请参见第13.1.19节“CREATE TABLESPACE Syntax”

  • innodb_support_xa

    属性
    命令行格式 --innodb-support-xa
    弃用 5.7.10
    系统变量 innodb_support_xa
    范围 全球,会议
    动态
    类型 布尔
    默认 TRUE

    启用InnoDB两相支持在提交XA事务,导致了交易准备一个额外的磁盘刷新。XA机制在内部使用,对于其二进制日志处于打开状态且正在接受来自多个线程的数据更改的任何服务器而言都是必不可少的。如果禁用 innodb_support_xa,则事务可以以不同于实时数据库提交的顺序的方式写入二进制日志,当二进制日志在灾难恢复或复制从属服务器中重播时,可以生成不同的数据。不要禁用 innodb_support_xa 在复制主服务器上,除非您有一个不寻常的设置,只有一个线程可以更改数据。

    innodb_support_xa已被弃用,并将在未来的MySQL版本中被删除。InnoDB 对于XA事务中的两阶段提交的支持始终从MySQL 5.7.10开始启用。禁用 innodb_support_xa不再是允许的,因为它会导致复制不安全并阻止与二进制日志组提交相关的性能提升。

  • innodb_sync_array_size

    属性
    命令行格式 --innodb-sync-array-size=#
    系统变量 innodb_sync_array_size
    范围 全球
    动态 没有
    类型 整数
    默认 1
    最低限度 1
    最大 1024

    定义互斥/锁等待数组的大小。增加值会拆分用于协调线程的内部数据结构,以便在具有大量等待线程的工作负载中实现更高的并发性。这个设置必须在MySQL实例启动时配置,并且以后不能更改。对于经常产生大量等待线程(通常大于768)的工作负载,建议增加此值。

  • innodb_sync_spin_loops

    属性
    命令行格式 --innodb-sync-spin-loops=#
    系统变量 innodb_sync_spin_loops
    范围 全球
    动态
    类型 整数
    默认 30
    最低限度 0
    最大 4294967295

    InnoDB在线程暂停之前 线程等待 互斥锁释放的次数。

  • innodb_sync_debug

    属性
    命令行格式 --innodb-sync-debug=#
    介绍 5.7.8
    系统变量 innodb_sync_debug
    范围 全球
    动态 没有
    类型 布尔
    默认 OFF

    启用InnoDB 存储引擎的同步调试检查该选项仅在使用CMake选项编译调试支持时可用 WITH_DEBUG

    以前,启用InnoDB同步调试检查需要使用CMake选项启用调试同步功能MySQL 5.7中引入了此配置选项后,此要求被删除。 ENABLE_DEBUG_SYNC

  • innodb_table_locks

    属性
    命令行格式 --innodb-table-locks
    系统变量 innodb_table_locks
    范围 全球,会议
    动态
    类型 布尔
    默认 TRUE

    如果autocommit = 0InnoDB荣誉LOCK TABLES; LOCK TABLES ... WRITE直到所有其他线程将所有锁释放到表中后,MySQL才会返回默认值 innodb_table_locks是1,这意味着LOCK TABLES 导致InnoDB在内部锁定表 autocommit = 0

    在MySQL 5.7中, innodb_table_locks = 0对显式锁定的表没有任何影响 LOCK TABLES ... WRITE它对LOCK TABLES ... WRITE隐式(例如通过触发器)或通过隐式读取或写入的表有效 LOCK TABLES ... READ

    相关信息请参见 第14.5节“InnoDB锁定和事务模型”

  • innodb_temp_data_file_path

    属性
    命令行格式 --innodb-temp-data-file-path=file
    介绍 5.7.1
    系统变量 innodb_temp_data_file_path
    范围 全球
    动态 没有
    类型
    默认 ibtmp1:12M:autoextend

    定义InnoDB 临时表空间 数据文件的相对路径,名称,大小和属性 如果您未指定值 innodb_temp_data_file_path,则缺省行为是ibtmp1在MySQL数据目录中创建一个稍大于12MB的自动扩展数据文件

    临时表空间数据文件规范的完整语法包括文件名,文件大小 autoextendmax 属性:

    file_namefile_size[:autoextend [:max:max_file_size]]
    

    临时表空间数据文件不能与另一个InnoDB数据文件具有相同的名称任何创建临时表空间数据文件的无效或错误都被视为致命错误,并且服务器启动被拒绝。临时表空间具有动态生成的空间ID,在每次服务器重新启动时可以更改该空间ID。

    文件大小通过追加指定KB,MB或GB(1024MB) KMG大小值。文件大小的总和必须略大于12MB。

    单个文件的大小限制取决于您的操作系统。在支持大文件的操作系统上,您可以将文件大小设置为4GB以上。不支持将原始磁盘分区用于临时表空间数据文件。

    autoextendmax 属性只能用于将最后一个指定的数据文件中使用 innodb_temp_data_file_path 的设置。例如:

    的[mysqld]
    innodb_temp_data_file_path = ibtmp1:50M; ibtmp2:12M:自动扩展:最大:500MB
    

    如果您指定了该autoextend选项,那么 InnoDB扩展数据文件(如果它的空闲空间不足)。autoextend增量是默认64MB。要修改增量,请更改 innodb_autoextend_increment 系统变量。

    临时表空间数据文件的完整目录路径是通过连接由innodb_data_home_dir定义的路径形成的 innodb_temp_data_file_path

    临时表空间由所有非压缩InnoDB临时表共享 压缩的临时表驻留在由tmpdir配置选项定义的临时文件目录中创建的每表文件表空间文件中

    InnoDB以只读模式运行之前,请将其设置 innodb_temp_data_file_path为数据目录之外的位置。该路径必须与数据目录相关。例如:

    --innodb_temp_data_file_path = .. / .. / .. / TMP / ibtmp1:12M:自动扩展         
    

    关于活动InnoDB临时表的元数据位于 INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO

    有关相关信息,请参见 第14.4.12节“临时表空间”

  • innodb_tmpdir

    属性
    命令行格式 --innodb-tmpdir=path
    介绍 5.7.11
    系统变量 innodb_tmpdir
    范围 全球,会议
    动态
    类型 目录名称
    默认 NULL

    用于为在ALTER TABLE重建表的联机操作期间创建的临时排序文件定义备用目录

    ALTER TABLE重建表的 联机操作还会在原始表的同一目录中创建一个 中间表文件。innodb_tmpdir选项不适用于中间表文件。

    有效值是MySQL数据目录路径以外的任何目录路径。如果该值为NULL(默认值),临时文件将创建MySQL临时目录($TMPDIR在Unix上,%TEMP% 在Windows上或由--tmpdir配置选项指定的目录 )。如果指定了目录,则只有在innodb_tmpdir使用SET 语句配置 目录和权限时才会检查目录和权限的存在 如果在目录字符串中提供符号链接,则符号链接将被解析并存储为绝对路径。路径不应超过512个字节。ALTER TABLE如果innodb_tmpdir设置为无效目录,在线 操作会报告错误innodb_tmpdir覆盖MySQL tmpdir设置,但仅限在线ALTER TABLE 操作。

    FILE权限需要配置 innodb_tmpdir

    innodb_tmpdir引入选项是为了避免溢出位于tmpfs文件系统上的临时文件目录 由于在ALTER TABLE重建表的联机操作期间创建大量临时排序文件,可能会发生此类溢出

    在复制环境中,innodb_tmpdir如果所有服务器具有相同的操作系统环境,则只考虑复制该 设置。否则,innodb_tmpdir在运行ALTER TABLE重建表的联机操作,复制设置可能会导致复制失败 如果服务器操作环境不同,建议您分别innodb_tmpdir在每台服务器上进行配置

    有关更多信息,请参阅 InnoDB存储临时文件的位置有关在线ALTER TABLE 操作的信息,请参见第14.13节“InnoDB和Online DDL”

  • innodb_thread_concurrency

    属性
    命令行格式 --innodb-thread-concurrency=#
    系统变量 innodb_thread_concurrency
    范围 全球
    动态
    类型 整数
    默认 0
    最低限度 0
    最大 1000

    InnoDB试图将操作系统线程的数量同时保持在 InnoDB小于或等于此变量给定的限制(InnoDB使用操作系统线程处理用户事务)。一旦线程数达到此限制,其他线程将进入先入先出(FIFO)队列中的等待状态供执行。等待锁的线程不计入并发执行线程的数量。

    此变量的范围是0到1000.值0(默认值)被解释为无限并发(无并发检查)。禁用线程并发检查可以InnoDB根据需要创建尽可能多的线程。值0也禁用queries inside InnoDBqueries in queue countersROW OPERATIONSSHOW ENGINE INNODB STATUS 输出。

    如果您的MySQL实例与其他应用程序共享CPU资源,或者您的工作负载或并发用户数量不断增加,请考虑设置此变量。正确的设置取决于工作负载,计算环境以及您正在运行的MySQL版本。您需要测试一系列值以确定提供最佳性能的设置。innodb_thread_concurrency是一个动态变量,它允许您在实时测试系统上尝试不同的设置。如果某个特定设置性能不佳,可以快速设置 innodb_thread_concurrency回0。

    使用以下准则来帮助查找并保持适当的设置:

    • 如果工作负载的并发用户线程数小于64,则设置 innodb_thread_concurrency=0

    • 如果您的工作负载始终很高或偶尔会出现高峰,请首先设置 innodb_thread_concurrency=128值,然后将值降至96,80,64等等,直到找到提供最佳性能的线程数。例如,假设您的系统通常有40到50个用户,但是周期性地增加到60,70甚至200.您发现80个并发用户的性能是稳定的,但开始显示回归超过这个数字。在这种情况下,您将设置 innodb_thread_concurrency=80避免影响性能。

    • 如果您不想InnoDB为用户线程使用超过一定数量的vCPU(例如20个vCPU),请设置 innodb_thread_concurrency为该数字(或可能较低,具体取决于性能结果)。如果您的目标是将MySQL与其他应用程序隔离,您可以考虑将mysqld进程专门绑定 到vCPU。但请注意,如果mysqld进程不一直繁忙,则独占绑定可能会导致非最佳硬件使用情况 在这种情况下,您可以将mysqld进程绑定 到vCPU,但也允许其他应用程序使用部分或全部vCPU。

      注意

      从操作系统的角度来看,使用资源管理解决方案来管理应用程序之间共享CPU时间的方式可能优于绑定该 mysqld过程。例如,您可以分配90%的vCPU的时间给定的应用程序,而其他关键进程运行,而当其他关键流程扩展该值回到40% 运行。

    • innodb_thread_concurrency 由于系统内部和资源争用的增加,过高的值可能导致性能回归。

    • 在某些情况下,最佳 innodb_thread_concurrency设置可能会小于vCPU的数量。

    • 定期监控和分析您的系统。工作负载,用户数量或计算环境的变化可能需要您调整 innodb_thread_concurrency设置。

    有关相关信息,请参见 第14.6.6节“为InnoDB配置线程并发”

  • innodb_trx_purge_view_update_only_debug

    属性
    命令行格式 --innodb-trx-purge-view-update-only-debug=#
    系统变量 innodb_trx_purge_view_update_only_debug
    范围 全球
    动态
    类型 布尔
    默认 OFF

    暂停清除删除标记的记录,同时允许更新清除视图。此选项人为地创建一个清除视图更新但尚未执行清除的情况。该选项仅在使用CMake选项编译调试支持时可用 WITH_DEBUG

  • innodb_trx_rseg_n_slots_debug

    属性
    命令行格式 --innodb-trx-rseg-n-slots-debug=#
    系统变量 innodb_trx_rseg_n_slots_debug
    范围 全球
    动态
    类型 整数
    默认 0
    最大 1024

    设置一个调试标志,该标志限制 TRX_RSEG_N_SLOTStrx_rsegf_undo_find_free查找撤消日志段的空闲槽函数的给定值 该选项仅在使用CMake选项编译调试支持时可用 WITH_DEBUG

  • innodb_thread_sleep_delay

    属性
    命令行格式 --innodb-thread-sleep-delay=#
    系统变量 innodb_thread_sleep_delay
    范围 全球
    动态
    类型(64位平台,<= 5.7.3) 整数
    类型(32位平台,<= 5.7.3) 整数
    类型(> = 5.7.4) 整数
    默认(64位平台,<= 5.7.3) 10000
    默认(32位平台,<= 5.7.3) 10000
    默认(> = 5.7.4) 10000
    最小(64位平台,<= 5.7.3) 0
    最小(32位平台,<= 5.7.3) 0
    最小(> = 5.7.4) 0
    最大(64位平台,<= 5.7.3) 18446744073709551615
    最大(32位平台,<= 5.7.3) 4294967295
    最大(> = 5.7.4) 1000000

    定义InnoDB线程在加入InnoDB队列之前的睡眠时间,以微秒为单位。默认值为10000.值为0将禁用睡眠。您可以将配置选项设置为 innodb_adaptive_max_sleep_delay 允许的最高值 innodb_thread_sleep_delay,并 根据当前的线程调度活动InnoDB自动调整 innodb_thread_sleep_delay向上或向下。这种动态调整有助于线程调度机制在系统轻载或接近满负载运行时顺利运行。

    有关更多信息,请参见 第14.6.6节“为InnoDB配置线程并发”

  • innodb_undo_directory

    属性
    命令行格式 --innodb-undo-directory=dir_name
    系统变量 innodb_undo_directory
    范围 全球
    动态 没有
    类型 目录名称
    默认(<= 5.7.7) .

    InnoDB创建撤消表空间 的路径通常用于将撤消日志放置在不同的存储设备上。innodb_rollback_segments一起使用 innodb_undo_tablespaces

    没有默认值(它是NULL)。如果未指定路径,则撤消表空间将在MySQL数据目录中创建,如定义的那样 datadir

    有关更多信息,请参见 部分14.7.7,“配置撤消表空间”

  • innodb_undo_log_truncate

    属性
    命令行格式 --innodb-undo-log-truncate=#
    介绍 5.7.5
    系统变量 innodb_undo_log_truncate
    范围 全球
    动态
    类型(> = 5.7.5) 布尔
    默认(> = 5.7.5) OFF

    启用时,撤消超过由其定义的阈值的表空间 innodb_max_undo_log_size被标记为截断。只有撤消表空间可以被截断。截断驻留在系统表空间中的撤消日志不受支持。要截断发生,必须至少有两个撤消表空间和两个配置为使用撤消表空间的重做启用撤消日志。这意味着 innodb_undo_tablespaces必须将其设置为等于或大于2 innodb_rollback_segments的值,并且 必须设置为等于或大于35的值。

    innodb_purge_rseg_truncate_frequency 配置选项可用于加速撤消tablepaces的截断。

    有关更多信息,请参见 第14.7.8节“截断撤消表空间”

  • innodb_undo_logs

    属性
    命令行格式 --innodb-undo-logs=#
    弃用 19年7月5日
    系统变量 innodb_undo_logs
    范围 全球
    动态
    类型 整数
    默认 128
    最低限度 1
    最大 128
    注意

    innodb_undo_logs 已弃用,将在未来版本中删除。

    定义的数量 回退段 由使用InnoDBinnodb_undo_logs选项是别名 innodb_rollback_segments有关更多信息,请参阅说明 innodb_rollback_segments

  • innodb_undo_tablespaces

    属性
    命令行格式 --innodb-undo-tablespaces=#
    弃用 21年7月5日
    系统变量 innodb_undo_tablespaces
    范围 全球
    动态 没有
    类型 整数
    默认 0
    最低限度 0
    最大(> = 5.7.8) 95
    最大值(<= 5.7.7) 126

    的数量撤消表空间由使用InnoDB默认值是0。

    注意

    innodb_undo_tablespaces 已弃用,将在未来版本中删除。

    由于在长时间运行的事务中撤消日志可能变大,因此在多个表空间中使用撤消日志可减少任何一个表空间的最大大小。撤消表空间文件是在由innodb_undo_directory名称形式定义的位置中创建 ,其中 是一系列表示空间ID的连续整数(包括前导零)。 undoNN

    撤消表空间文件的初始大小取决于该 innodb_page_size值。对于默认的16k InnoDB页大小,初始撤消表空间文件大小为10MiB。对于4k,8k,32k和64k页大小,初始撤消表空间文件大小分别为7MiB,8MiB,20MiB和40MiB。

    至少需要两个撤消表空间才能启用撤销日志的截断。请参见 第14.7.8节“截断撤消表空间”

    重要

    innodb_undo_tablespaces只能在初始化MySQL实例之前进行配置,之后不能更改。如果未指定值,则使用默认设置0初始化实例。尝试InnoDB使用比初始化MySQL实例时指定的更大数量的还原表空间重新启动会导致启动失败并显示错误,指出InnoDB未找到预期的值撤消表空间的数量。

    临时表撤消日志中所述,将128个回滚段中的32个保留用于临时表 一个回滚段总是分配给系统表空间,这样可以为撤消表空间留下95个回滚段。这意味着 innodb_undo_tablespaces 最大限制是95。

    有关更多信息,请参见 部分14.7.7,“配置撤消表空间”

  • innodb_use_native_aio

    属性
    命令行格式 --innodb-use-native-aio=#
    系统变量 innodb_use_native_aio
    范围 全球
    动态 没有
    类型 布尔
    默认 ON

    指定是否使用Linux异步I / O子系统。此变量仅适用于Linux系统,并且在服务器运行时无法更改。通常,您不需要配置此选项,因为它默认情况下处于启用状态。

    Linux系统上提供了Windows系统上异步I / O功能InnoDB(其他类Unix系统继续使用同步I / O调用。)此功能提高了大量I / O绑定系统的可伸缩性,这些系统通常会在SHOW ENGINE INNODB STATUS\G输出中显示许多待执行的读取/写入操作

    运行大量InnoDBI / O线程,特别是在同一台服务器上运行多个此类实例时,可能会超出Linux系统的容量限制。在这种情况下,您可能会收到以下错误:

    EAGAIN:指定的maxevents超出用户对可用事件的限制。
    

    您通常可以通过写入更高的限制来解决此错误/proc/sys/fs/aio-max-nr

    但是,如果操作系统中的异步I / O子系统的问题阻止InnoDB启动,则可以使用启动服务器 innodb_use_native_aio=0如果InnoDB检测到潜在问题(例如tmpdir位置, tmpfs文件系统和不支持AIO的Linux内核的组合),则也可能在启动期间自动禁用此选项 tmpfs

    有关更多信息,请参见 第14.6.8节“在Linux上使用异步I / O”

  • innodb_use_sys_malloc

    属性
    命令行格式 --innodb-use-sys-malloc=#
    弃用 是(在5.7.4中删除)
    系统变量 innodb_use_sys_malloc
    范围 全球
    动态 没有
    类型 布尔
    默认 ON

    启用操作系统内存分配器。如果禁用,则 InnoDB使用其自己的分配器。默认值是ON有关更多信息,请参见 第14.6.4节“为InnoDB配置内存分配器”

    innodb_use_sys_malloc 在MySQL 5.7中被删除。

  • innodb_version

    InnoDB版本号。在MySQL 5.7中,单独的版本编号 InnoDB不适用,并且此值version与服务器编号相同

  • innodb_write_io_threads

    属性
    命令行格式 --innodb-write-io-threads=#
    系统变量 innodb_write_io_threads
    范围 全球
    动态 没有
    类型 整数
    默认 4
    最低限度 1
    最大 64

    用于写入操作的I / O线程数 InnoDB缺省值是4.它与读取线程的对应关系是 innodb_read_io_threads有关更多信息,请参见 第14.6.7节“配置背景InnoDB I / O线程数”有关通用I / O优化建议,请参见 第8.5.8节“优化InnoDB磁盘I / O”

    注意

    在Linux系统上运行多个MySQL服务器(通常超过12)与默认设置 innodb_read_io_threadsinnodb_write_io_threads以及Linux的 aio-max-nr设置可以超过系统限制。理想情况下,增加aio-max-nr 设置; 作为一种解决方法,您可以减少一个或两个MySQL配置选项的设置。

    还要考虑 sync_binlog控制二进制日志同步到磁盘的值。

    有关通用I / O优化建议,请参见 第8.5.8节“优化InnoDB磁盘I / O”

14.15 InnoDB INFORMATION_SCHEMA表

本节提供InnoDB INFORMATION_SCHEMA表格的信息和使用示例

InnoDB INFORMATION_SCHEMA 表提供了有关InnoDB存储引擎各个方面的元数据,状态信息和统计信息您可以InnoDB INFORMATION_SCHEMA通过SHOW TABLESINFORMATION_SCHEMA数据库发布声明 来查看的列表

MySQL的> SHOW TABLES FROM INFORMATION_SCHEMA LIKE 'INNODB%';

有关表格定义,请参见第24.31节“InnoDB INFORMATION_SCHEMA表格”有关MySQL INFORMATION_SCHEMA数据库的一般信息,请参阅 第24章INFORMATION_SCHEMA表

14.15.1 InnoDB INFORMATION_SCHEMA关于压缩的表

有两对InnoDB INFORMATION_SCHEMA关于压缩表格可以提供对整体压缩效果如何的深入了解:

14.15.1.1 INNODB_CMP和INNODB_CMP_RESET

INNODB_CMPINNODB_CMP_RESET 表包含与压缩表执行的操作,这被描述的状态信息 14.9节,“InnoDB的表和页压缩”PAGE_SIZE列报告压缩的 页面大小

这两个表具有相同的内容,但读取 INNODB_CMP_RESET 重置压缩和解压缩操作的统计信息。例如,如果您INNODB_CMP_RESET 每隔60分钟输出 一次,则会看到每个小时的统计数据。如果您监控INNODB_CMP(确保永不读取 INNODB_CMP_RESET的输出 ,您会看到InnoDB启动以来的累计统计数据。

有关表定义,请参见 第24.31.4节“INFORMATION_SCHEMA INNODB_CMP和INNODB_CMP_RESET表”

14.15.1.2 INNODB_CMPMEM和INNODB_CMPMEM_RESET

INNODB_CMPMEMINNODB_CMPMEM_RESET 表包含驻留在缓冲池中压缩页的状态信息。请参阅 第14.9节“InnoDB表和页面压缩”以获取有关压缩表和缓冲池使用的更多信息。INNODB_CMPINNODB_CMP_RESET 表格应提供关于压缩的更多有用的统计数据。

内部细节

InnoDB使用 好友分配器 系统来管理分配给各种大小页面的内存 ,从1KB到16KB。这里描述的两个表中的每一行对应于单个页面大小。

INNODB_CMPMEMINNODB_CMPMEM_RESET 表的内容相同,但是从阅读 INNODB_CMPMEM_RESET 重置迁址操作的统计信息。例如,如果每隔60分钟存档一次输出 INNODB_CMPMEM_RESET,则会显示小时统计。如果您从不读取 INNODB_CMPMEM_RESET 和监控输出 INNODB_CMPMEM,它会显示自InnoDB 启动以来的累计统计数据

有关表定义,请参见 第24.31.5节“INFORMATION_SCHEMA INNODB_CMPMEM和INNODB_CMPMEM_RESET表”

14.15.1.3使用压缩信息模式表

例14.1使用压缩信息模式表

以下是从包含压缩表(见数据库样本输出第14.9节,“InnoDB的表和页压缩”INNODB_CMPINNODB_CMP_PER_INDEX,和 INNODB_CMPMEM)。

下表显示INFORMATION_SCHEMA.INNODB_CMP 了轻工作负载的内容 缓冲池包含的唯一压缩页面大小为8K。压缩或解压缩的网页已经消耗不到,因为统计数字重置时间的第二,因为列COMPRESS_TIMEUNCOMPRESS_TIME为零。

页面大小 压缩操作 压缩操作正常 压缩时间 解压缩操作 解压缩时间
1024 0 0 0 0 0
2048 0 0 0 0 0
4096 0 0 0 0 0
8192 1048 921 0 61 0
16384 0 0 0 0 0

据说INNODB_CMPMEM缓冲池中有6169个压缩的8KB页面 唯一的其他分配的块大小是64个字节。最小的 PAGE_SIZEin INNODB_CMPMEM用于缓冲池中没有未压缩页面的压缩页面的块描述符。我们看到有5910个这样的页面。间接地,我们看到259(6169-5910)压缩页面也以非压缩形式存在于缓冲池中。

下表显示INFORMATION_SCHEMA.INNODB_CMPMEM 了轻工作负载的内容 由于压缩页面的内存分配器碎片,某些内存不可用: SUM(PAGE_SIZE*PAGES_FREE)=6784这是因为小内存分配请求是通过使用伙伴分配系统从主缓冲池分配的16K块开始分割更大的块来实现的。碎片是这么低,因为一些分配的块已经被重新定位(复制)以形成更大的相邻空闲块。这种SUM(PAGE_SIZE*RELOCATION_OPS)字节的复制 消耗不到一秒钟 (SUM(RELOCATION_TIME)=0)

页面大小 使用的页面 页面免费 搬迁运营 搬迁时间
64 5910 0 2436 0
128 0 1 0 0
256 0 0 0 0
512 0 1 0 0
1024 0 0 0 0
2048 0 1 0 0
4096 0 1 0 0
8192 6169 0 0
16384 0 0 0 0

14.15.2 InnoDB INFORMATION_SCHEMA事务和锁定信息

使用三个InnoDB INFORMATION_SCHEMA表可以监视事务并诊断潜在的锁定问题:

  • INNODB_TRX:包含有关当前内部执行的每个事务的信息 InnoDB,包括事务状态(例如,是否正在运行或正在等待锁),事务何时开始以及事务正在执行的特定SQL语句。

  • INNODB_LOCKS:在InnoDB的每个事务正在等待另一事务释放锁(INNODB_TRX.TRX_STATELOCK WAIT)由恰好一个阻挡锁请求阻止。该阻塞锁请求是针对另一个事务处于不兼容模式下的行或表锁。阻止事务的锁始终保持与请求的锁定模式不兼容的模式(读取与写入,共享与独占)。在其他事务提交或回滚之前,被阻止的事务不能继续,从而释放所请求的锁。对于每个被阻止的事务,都 INNODB_LOCKS包含一行描述事务请求的每个锁以及它正在等待的锁。 INNODB_LOCKS还包含一个行的每个阻塞另一个事务,锁定不管这持有锁的事务的状态(INNODB_TRX.TRX_STATERUNNINGLOCK WAITROLLING BACKCOMMITTING)。

  • INNODB_LOCK_WAITS:该表指示哪些事务正在等待给定的锁,或者给定事务正在等待哪个锁。此表包含每个被阻止的事务的一个或多个行,指示它所请求的锁和任何阻止该请求的锁。REQUESTED_LOCK_ID值指的是事务请求的锁,并且该 BLOCKING_LOCK_ID值指的是阻止第一个事务继续进行的锁(由另一个事务持有)。对于任何给定的被阻止事务,所有行都 INNODB_LOCK_WAITS具有相同的值REQUESTED_LOCK_ID和不同的值BLOCKING_LOCK_ID

有关上述表格的更多信息,请参见 第24.31.27节“INFORMATION_SCHEMA INNODB_TRX表”第24.31.13节“INFORMATION_SCHEMA INNODB_LOCKS表”第24.31.14节“INFORMATION_SCHEMA INNODB_LOCK_WAITS表”

14.15.2.1使用InnoDB事务和锁定信息

识别阻塞事务

识别另一个事务块有时很有用。包含有关InnoDB事务和数据锁定信息的表 使您能够确定哪个事务正在等待另一个事务以及正在请求哪个资源。(有关这些表的说明,请参见 第14.15.2节“InnoDB INFORMATION_SCHEMA事务和锁定信息”。)

假设三个会话正在同时运行。每个会话对应一个MySQL线程,并且一个接一个地执行一个事务。当这些会议发布以下声明时,请考虑系统的状态,但是还没有人提交它的事务:

  • 会议A:

    开始;
    选择一个FROM t FOR UPDATE;
    SELECT SLEEP(100);
    
  • 会议B:

    SELECT b FROM t FOR UPDATE;
    
  • 会议C:

    SELECT c FROM t FOR UPDATE;
    

在这种情况下,请使用以下查询来查看哪些事务正在等待以及哪些事务阻止它们:

选择
  r.trx_id waiting_trx_id,
  r.trx_mysql_thread_id waiting_thread,
  r.trx_query waiting_query,
  b.trx_id blocking_trx_id,
  b.trx_mysql_thread_id blocking_thread,
  b.trx_query blocking_query
FROM information_schema.innodb_lock_waits w
INNER JOIN information_schema.innodb_trx b
  ON b.trx_id = w.blocking_trx_id
INNER JOIN information_schema.innodb_trx r
  ON r.trx_id = w.requesting_trx_id;

或者更简单地说,使用sys模式 innodb_lock_waits视图:

选择
  waiting_trx_id,
  waiting_pid,
  waiting_query,
  blocking_trx_id,
  blocking_pid,
  blocking_query
FROM sys.innodb_lock_waits;

如果阻塞查询报告了NULL值,请参阅 在发布会话变为空闲后识别阻塞查询

等待trx id 等待线程 等待查询 阻止trx id 阻塞线程 阻止查询
A4 6 SELECT b FROM t FOR UPDATE A3 5 SELECT SLEEP(100)
A5 7 SELECT c FROM t FOR UPDATE A3 5 SELECT SLEEP(100)
A5 7 SELECT c FROM t FOR UPDATE A4 6 SELECT b FROM t FOR UPDATE

在上表中,您可以通过等待查询阻止查询来识别会话 如你看到的:

  • 会话B(trx id A4,线程 6)和会话C(trx id A5,线程7)都等待会话A(trx id A3,线程5)。

  • 会话C正在等待会话B以及会话A.

你可以看到表中的基础数据 INNODB_TRXINNODB_LOCKS以及 INNODB_LOCK_WAITS

下表显示了一些示例内容 INFORMATION_SCHEMA.INNODB_TRX

trx id trx状态 trx开始了 trx请求的锁定ID trx等待开始 trx重量 trx mysql线程ID trx查询
A3 RUN­NING 2008-01-15 16:44:54 NULL NULL 2 5 SELECT SLEEP(100)
A4 LOCK WAIT 2008-01-15 16:45:09 A4:1:3:2 2008-01-15 16:45:09 2 6 SELECT b FROM t FOR UPDATE
A5 LOCK WAIT 2008-01-15 16:45:14 A5:1:3:2 2008-01-15 16:45:14 2 7 SELECT c FROM t FOR UPDATE

下表显示了一些示例内容 INFORMATION_SCHEMA.INNODB_LOCKS

锁定ID 锁定trx id 锁定模式 锁定类型 锁表 锁定索引 锁定数据
A3:1:3:2 A3 X RECORD test.t PRIMARY 0x0200
A4:1:3:2 A4 X RECORD test.t PRIMARY 0x0200
A5:1:3:2 A5 X RECORD test.t PRIMARY 0x0200

下表显示了一些示例内容 INFORMATION_SCHEMA.INNODB_LOCK_WAITS

请求trx id 请求的锁定ID 阻止trx id 阻止锁定ID
A4 A4:1:3:2 A3 A3:1:3:2
A5 A5:1:3:2 A3 A3:1:3:2
A5 A5:1:3:2 A4 A4:1:3:2
在发布会变得空闲后识别阻塞查询

在识别阻塞事务时,如果发出查询的会话已变为空闲,则会为阻塞查询报告NULL值。在这种情况下,请使用以下步骤确定阻止查询:

  1. 识别阻塞事务的进程列表ID。sys.innodb_lock_waits 表中,阻塞事务的流程列表ID是blocking_pid值。

  2. 使用blocking_pid查询MySQL性能模式threads 表来确定THREAD_ID阻塞事务。例如,如果 blocking_pid是6,请发出以下查询:

    SELECT THREAD_ID FROM performance_schema.threads WHERE PROCESSLIST_ID = 6;
    
  3. 使用THREAD_ID查询性能模式 events_statements_current 表来确定线程执行的最后一个查询。例如,如果THREAD_ID是28,请发出以下查询:

    SELECT THREAD_ID,SQL_TEXT FROM performance_schema.events_statements_current 
    WHERE THREAD_ID = 28 \ G
    
  4. 如果线程执行的最后一个查询没有足够的信息来确定为什么锁持有,您可以查询Performance Schema events_statements_history 表以查看线程执行的最后10条语句。

    SELECT THREAD_ID,SQL_TEXT FROM performance_schema.events_statements_history 
    WHERE THREAD_ID = 28 ORDER BY EVENT_ID;
    
将InnoDB事务与MySQL会话相关联

有时将内部InnoDB锁定信息与MySQL维护的会话级信息关联起来会很有用 例如,对于给定的InnoDB 事务标识,您可能想知道对应的MySQL会话标识和可能持有锁的会话的名称,从而阻止其他事务。

以下来自INFORMATION_SCHEMA表格的输出来自 一个稍微加载的系统。可以看出,有几个交易正在运行。

以下INNODB_LOCKSINNODB_LOCK_WAITS表格显示:

  • 交易77F(执行的 INSERT)正在等待交易77E77D以及77B提交。

  • 事务77E(正在执行的 INSERT)正在等待事务77D77B提交。

  • 事务77D(正在执行 INSERT)正在等待事务77B提交。

  • 事务77B(正在执行 INSERT)正在等待事务77A提交。

  • 事务77A正在运行,当前正在执行SELECT

  • 事务E56(正在执行 INSERT)正在等待事务E55提交。

  • 事务E55(正在执行 INSERT)正在等待事务19C提交。

  • 事务19C正在运行,正在执行一个INSERT

注意

INFORMATION_SCHEMA PROCESSLISTINNODB_TRX表中显示的查询之间可能存在不一致 有关说明,请参见 第14.15.2.3节“InnoDB事务和锁定信息的持久性和一致性”

下表显示了INFORMATION_SCHEMA.PROCESSLIST 运行繁重工作负载的系统 的内容

ID 用户 主办 D B 命令 时间 信息
384 root localhost test Query 10 update INSERT INTO t2 VALUES …
257 root localhost test Query 3 update INSERT INTO t2 VALUES …
130 root localhost test Query 0 update INSERT INTO t2 VALUES …
61 root localhost test Query 1 update INSERT INTO t2 VALUES …
8 root localhost test Query 1 update INSERT INTO t2 VALUES …
4 root localhost test Query 0 preparing SELECT * FROM PROCESSLIST
2 root localhost test Sleep 566 NULL

下表显示了INFORMATION_SCHEMA.INNODB_TRX运行繁重工作负载的系统 的内容

trx id trx状态 trx开始了 trx请求的锁定ID trx等待开始 trx重量 trx mysql线程ID trx查询
77F LOCK WAIT 2008-01-15 13:10:16 77F 2008-01-15 13:10:16 1 876 INSERT INTO t09 (D, B, C) VALUES …
77E LOCK WAIT 2008-01-15 13:10:16 77E 2008-01-15 13:10:16 1 875 INSERT INTO t09 (D, B, C) VALUES …
77D LOCK WAIT 2008-01-15 13:10:16 77D 2008-01-15 13:10:16 1 874 INSERT INTO t09 (D, B, C) VALUES …
77B LOCK WAIT 2008-01-15 13:10:16 77B:733:12:1 2008-01-15 13:10:16 4 873 INSERT INTO t09 (D, B, C) VALUES …
77A RUN­NING 2008-01-15 13:10:16 NULL NULL 4 872 SELECT b, c FROM t09 WHERE …
E56 LOCK WAIT 2008-01-15 13:10:06 E56:743:6:2 2008-01-15 13:10:06 5 384 INSERT INTO t2 VALUES …
E55 LOCK WAIT 2008-01-15 13:10:06 E55:743:38:2 2008-01-15 13:10:13 965 257 INSERT INTO t2 VALUES …
19C RUN­NING 2008-01-15 13:09:10 NULL NULL 2900 130 INSERT INTO t2 VALUES …
E15 RUN­NING 2008-01-15 13:08:59 NULL NULL 5395 61 INSERT INTO t2 VALUES …
51D RUN­NING 2008-01-15 13:08:47 NULL NULL 9807 8 INSERT INTO t2 VALUES …

下表显示了INFORMATION_SCHEMA.INNODB_LOCK_WAITS 运行繁重工作负载的系统 的内容

请求trx id 请求的锁定ID 阻止trx id 阻止锁定ID
77F 77F:806 77E 77E:806
77F 77F:806 77D 77D:806
77F 77F:806 77B 77B:806
77E 77E:806 77D 77D:806
77E 77E:806 77B 77B:806
77D 77D:806 77B 77B:806
77B 77B:733:12:1 77A 77A:733:12:1
E56 E56:743:6:2 E55 E55:743:6:2
E55 E55:743:38:2 19C 19C:743:38:2

下表显示了INFORMATION_SCHEMA.INNODB_LOCKS 运行繁重工作负载的系统 的内容

锁定ID 锁定trx id 锁定模式 锁定类型 锁表 锁定索引 锁定数据
77F:806 77F AUTO_INC TABLE test.t09 NULL NULL
77E:806 77E AUTO_INC TABLE test.t09 NULL NULL
77D:806 77D AUTO_INC TABLE test.t09 NULL NULL
77B:806 77B AUTO_INC TABLE test.t09 NULL NULL
77B:733:12:1 77B X RECORD test.t09 PRIMARY supremum pseudo-record
77A:733:12:1 77A X RECORD test.t09 PRIMARY supremum pseudo-record
E56:743:6:2 E56 S RECORD test.t2 PRIMARY 0, 0
E55:743:6:2 E55 X RECORD test.t2 PRIMARY 0, 0
E55:743:38:2 E55 S RECORD test.t2 PRIMARY 1922, 1922
19C:743:38:2 19C X RECORD test.t2 PRIMARY 1922, 1922

14.15.2.2 InnoDB锁定和锁定等待信息

当一个事务在一个表中更新了一行,或将其锁定 SELECT FOR UPDATEInnoDB 建立在该行锁的列表或队列。同样, InnoDB维护表级锁的列表。如果第二个事务想要以不兼容的模式更新行或锁定已被先前事务锁定的表,InnoDB请将该行的锁定请求添加到相应的队列。对于事务获取的锁,必须删除以前输入到该行或表的锁定队列中的所有不兼容的锁请求(发生在持有或请求这些锁的事务提交或回滚时)。

对于不同的行或表,事务可能有任意数量的锁请求。在任何特定时间,交易都可以请求由另一个交易持有的锁,在这种情况下,该交易被该另一个交易阻止。请求事务必须等待持有阻塞锁的事务提交或回滚。如果一个事务没有等待一个锁,它就处于一个RUNNING状态。如果一个事务正在等待一个锁,它就处于一个LOCK WAIT 状态。(该INFORMATION_SCHEMA INNODB_TRX表指示事务状态值。)

INNODB_LOCKS表为每个LOCK WAIT事务保存一行或多行,指示阻止其进展的任何锁定请求。该表还包含一行,用于描述给定行或表的挂起队列中的每个锁。INNODB_LOCK_WAITS表显示事务已保存的哪些锁定正在阻止其他事务请求的锁定。

14.15.2.3 InnoDB事务和锁定信息的持久性和一致性

由交易和锁定表公开的数据(INNODB_TRXINNODB_LOCKS,和 INNODB_LOCK_WAITS)表示窥探到快速变化的数据。这不像用户表,其中数据仅在应用程序启动的更新发生时才更改。基础数据是内部系统管理的数据,并且可以快速更改。

出于性能方面的考虑,为了尽量减少事务和锁定表之间InnoDB误入连接的可能性,只要SELECT发布任何表, 就将所需的事务和锁定信息收集到中间缓冲区中 只有在自上次读取缓冲区起超过0.1秒时,才会刷新此缓冲区。填充这三个表所需的数据是以原子方式一致地获取的,并保存在此全局内部缓冲区中,形成一个时间点 快照如果在0.1秒内发生多次表访问(因为当MySQL处理这些表之间的连接时它们几乎肯定会发生),则使用相同的快照来满足查询。

当您在单个查询中将这些表中的任何一个连接在一起时,会返回正确的结果,因为三个表的数据来自同一个快照。因为缓冲区不会被任何这些表的每个查询刷新,所以如果您在十分之一秒内针对这些表发出单独的查询,则查询结果与查询相同。另一方面,对于相同或不同表格发出的两次不同查询,可能会看到不同的结果,因为数据来自不同的快照。

由于InnoDB在收集事务和锁定数据时必须暂时停止,因此如果其他用户看到这些表的频繁查询会对性能产生负面影响。

由于这些表包含敏感信息(至少 INNODB_LOCKS.LOCK_DATAINNODB_TRX.TRX_QUERY),出于安全原因,只有具有该PROCESS权限的用户才可以SELECT从中获得。

如前所述,填充所述交易和锁定表(数据INNODB_TRXINNODB_LOCKSINNODB_LOCK_WAITS)被自动提取并保存到提供的中间缓冲器点即时快照。当从同一快照查询时,所有三个表中的数据都是一致的。但是,基础数据变化如此之快,以至于类似快速变化数据的类似瞥见可能不会同步。因此,在比较InnoDB事务中的数据和锁定表中的数据时应该小心PROCESSLIST数据来自PROCESSLIST表不是来自与关于锁定和事务的数据相同的快照。即使您发出单个 SELECT(加入 INNODB_TRXPROCESSLIST例如),这些表的内容通常也不一致。 INNODB_TRX可能引用行中不存在PROCESSLIST或当前正在执行的SQL查询中显示的事务 INNODB_TRX.TRX_QUERY可能不同于在PROCESSLIST.INFO

14.15.3 InnoDB INFORMATION_SCHEMA系统表

您可以提取有关InnoDB使用InnoDB INFORMATION_SCHEMA系统表管理的模式对象的元数据 这些信息来自InnoDB内部系统表(也称为InnoDB 数据字典),不能像常规InnoDB一样直接查询 传统上,您将使用第14.17节“InnoDB监视器”中的技术获取此类信息 ,设置 InnoDB监视器并解析SHOW ENGINE INNODB STATUS语句的输出 InnoDB INFORMATION_SCHEMA表界面允许您使用SQL查询数据。

除了 INNODB_SYS_TABLESTATS没有相应内部系统表的系统表外, InnoDB INFORMATION_SCHEMA 系统表中填充的数据直接从内部InnoDB系统表中读取,而不是从内存中缓存的元数据中读取

InnoDB INFORMATION_SCHEMA 系统表格包括下面列出的表格。 INNODB_SYS_DATAFILES并且 INNODB_SYS_TABLESPACES在MySQL 5.6.6中添加了对语句子句的支持,该语句允许在MySQL数据目录之外的位置创建按文件表的表 空间(文件)。 DATA DIRECTORY='directory'CREATE TABLEInnoDB .ibd

MySQL的> SHOW TABLES FROM INFORMATION_SCHEMA LIKE 'INNODB_SYS%';
+ -------------------------------------------- +
| Tables_in_information_schema(INNODB_SYS%)|
+ -------------------------------------------- +
| INNODB_SYS_DATAFILES |
| INNODB_SYS_TABLESTATS |
| INNODB_SYS_FOREIGN |
| INNODB_SYS_COLUMNS |
| INNODB_SYS_INDEXES |
| INNODB_SYS_FIELDS |
| INNODB_SYS_TABLESPACES |
| INNODB_SYS_FOREIGN_COLS |
| INNODB_SYS_TABLES |
+ -------------------------------------------- +

表格名称表示提供的数据类型:

  • INNODB_SYS_TABLES提供有关InnoDB表的元数据,等同SYS_TABLESInnoDB数据字典中表中的信息。

  • INNODB_SYS_COLUMNS提供有关InnoDB表列的元数据,等同 SYS_COLUMNSInnoDB数据字典中表中的 信息。

  • INNODB_SYS_INDEXES提供有关InnoDB索引的元数据,等同SYS_INDEXESInnoDB数据字典中表中的信息。

  • INNODB_SYS_FIELDS提供有关InnoDB索引键列(字段)的元数据 ,等同SYS_FIELDSInnoDB数据字典中表中的 信息。

  • INNODB_SYS_TABLESTATS提供了有关InnoDB从内存数据结构派生的表的低级状态信息的视图 没有相应的内部 InnoDB系统表。

  • INNODB_SYS_DATAFILESInnoDB 文件每表和数据字典提供数据文件路径信息,相当于SYS_DATAFILES表中的InnoDB信息。

  • INNODB_SYS_TABLESPACES提供关于InnoDB每个表和一般表空间的元数据,等同 SYS_TABLESPACESInnoDB数据字典中表中的 信息。

  • INNODB_SYS_FOREIGN提供有关在InnoDB表上定义的外键的元数据 ,等同SYS_FOREIGNInnoDB数据字典中表中的 信息。

  • INNODB_SYS_FOREIGN_COLS提供有关在表上定义的外键列的元数据 InnoDB,等同SYS_FOREIGN_COLSInnoDB数据字典中表中的信息。

InnoDB INFORMATION_SCHEMA 系统表可通过领域,如连接在一起 TABLE_IDINDEX_IDSPACE,让您轻松检索所有可用的数据,你想学习或监视的对象。

有关每个表的列的信息, 请参阅InnoDB INFORMATION_SCHEMA文档。

例14.2 InnoDB INFORMATION_SCHEMA系统表

本示例使用一个t1带有单个索引(i1的简单table(来演示在InnoDB INFORMATION_SCHEMA系统表中找到的元数据的类型

  1. 创建一个测试数据库和表格t1

    MySQL的> CREATE DATABASE test;
    
    MySQL的> USE test;
    
    MySQL的> CREATE TABLE t1 (
           col1 INT,
           col2 CHAR(10),
           col3 VARCHAR(10))
           ENGINE = InnoDB;
    
    MySQL的> CREATE INDEX i1 ON t1(col1);
    
  2. 创建表后t1,查询 INNODB_SYS_TABLES以找到元数据test/t1

    MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME='test/t1' \G
    *************************** 1. row ******************** *******
         TABLE_ID:71
             NAME:test / t1
             FLAG:1
           N_COLS:6
            空间:57
      FILE_FORMAT:羚羊
       ROW_FORMAT:紧凑
    ZIP_PAGE_SIZE:0
    ...
    

    表格t1TABLE_ID71个FLAG字段。该 字段提供有关表格格式和存储特征的位级信息。有六列,其中三个是通过创建隐藏的列 InnoDBDB_ROW_IDDB_TRX_ID,和 DB_ROLL_PTR)。表的ID SPACE是57(值为0表示该表驻留在系统表空间中)。FILE_FORMAT是羚羊和 ROW_FORMAT紧凑。 ZIP_PAGE_SIZE仅适用于具有Compressed行格式的表格

  3. 使用TABLE_ID来自信息 INNODB_SYS_TABLES,查询 INNODB_SYS_COLUMNS表格以获取关于表格列的信息。

    MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS where TABLE_ID = 71 \G
    *************************** 1. row ******************** *******
    TABLE_ID:71
        名称:col1
         POS:0
       MTYPE:6
      PRTYPE:1027
         LEN:4
    *************************** 2. row ******************** *******
    TABLE_ID:71
        名称:col2
         POS:1
       MTYPE:2
      PRTYPE:524542
         LEN:10
    *************************** 3. row ******************** *******
    TABLE_ID:71
        名称:col3
         POS:2
       MTYPE:1
      PRTYPE:524303
         LEN:10
    

    除了TABLE_ID和列之外 NAMEINNODB_SYS_COLUMNS还提供了POS每列的序号位置()(从0开始并依次递增),列 MTYPE主类型(6 = INT,2 = CHAR,1 = VARCHAR),PRTYPE精确键入(代表MySQL数据类型,字符集代码和可空性的二进制值)和列长度(LEN)。

  4. 再次 使用这些TABLE_ID信息 INNODB_SYS_TABLES,查询INNODB_SYS_INDEXES有关与表关联的索引的信息 t1

    MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_INDEXES WHERE TABLE_ID = 71 \G
    *************************** 1. row ******************** *******
           INDEX_ID:111
               名称:GEN_CLUST_INDEX
           TABLE_ID:71
               类型:1
           N_FIELDS:0
            PAGE_NO:3
              空间:57
    MERGE_THRESHOLD:50
    *************************** 2. row ******************** *******
           INDEX_ID:112
               姓名:i1
           TABLE_ID:71
               类型:0
           N_FIELDS:1
            PAGE_NO:4
              空间:57
    MERGE_THRESHOLD:50
    

    INNODB_SYS_INDEXES返回两个索引的数据。第一个索引是 GEN_CLUST_INDEXInnoDB如果表没有用户定义的聚簇索引,则这是一个聚簇索引。第二个索引(i1)是用户定义的二级索引。

    INDEX_ID是在实例中的所有数据库中唯一的索引的标识符。TABLE_ID识别出索引与相关联的表。索引TYPE值指示索引 的类型(1 =集群索引,0 =辅助索引)。N_FILEDS值是构成索引的字段的数量。PAGE_NO是索引B树的根页码,并且 SPACE是索引所在表空间的ID。非零值表示索引不驻留在系统表空间中。 MERGE_THRESHOLD定义索引页面中数据量的百分比阈值。如果索引页中的数据量在删除某行或通过更新操作缩短行时降至此值(缺省值为50%)以下,则 InnoDB尝试合并索引页与相邻索引页。

  5. 使用INDEX_ID来自信息 INNODB_SYS_INDEXES,查询 INNODB_SYS_FIELDS有关索引字段的信息i1

    MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FIELDS where INDEX_ID = 112 \G
    *************************** 1. row ******************** *******
    INDEX_ID:112
        名称:col1
         POS:0
    

    INNODB_SYS_FIELDS提供 NAME索引内的索引字段及其序号位置。如果索引(i1)已在多个字段中定义, INNODB_SYS_FIELDS则会为每个索引字段提供元数据。

  6. 利用SPACE从信息 INNODB_SYS_TABLES,查询 INNODB_SYS_TABLESPACES表中有关表的表空间信息。

    MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE = 57 \G
    *************************** 1. row ******************** *******
            空间:57
             NAME:test / t1
             FLAG:0
      FILE_FORMAT:羚羊
       ROW_FORMAT:紧凑或冗余
        PAGE_SIZE:16384
    ZIP_PAGE_SIZE:0
    

    除了SPACE表空间ID和NAME关联的表之外,INNODB_SYS_TABLESPACES 还提供表空间FLAG数据,这是关于表空间格式和存储特性的位级别信息。还提供的表空间 FILE_FORMATROW_FORMATPAGE_SIZE,和其他几个表空间元数据项。

  7. 再次 使用该SPACE信息 INNODB_SYS_TABLES,查询INNODB_SYS_DATAFILES表空间数据文件的位置。

    MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_DATAFILES WHERE SPACE = 57 \G
    *************************** 1. row ******************** *******
    空间:57
     路径:./test/t1.ibd
    

    数据文件位于test MySQL目录下的data目录中。如果 使用 语句子句在MySQL数据目录之外的位置创建文件每表的表空间,则表空间将是完全限定的目录路径。 DATA DIRECTORYCREATE TABLEPATH

  8. 作为最后一步,在table t1TABLE_ID = 71)中插入一行 并查看INNODB_SYS_TABLESTATS表中的数据 MySQL表优化器使用此表中的数据计算在查询InnoDB时要使用哪个索引 这些信息来源于内存中的数据结构。没有相应的内部InnoDB系统表。

    MySQL的> INSERT INTO t1 VALUES(5, 'abc', 'def');
    查询OK,1行受影响(0.06秒)
    
    MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS where TABLE_ID = 71 \G
    *************************** 1. row ******************** *******
             TABLE_ID:71
                 NAME:test / t1
    STATS_INITIALIZED:已初始化
             NUM_ROWS:1
     CLUST_INDEX_SIZE:1
     OTHER_INDEX_SIZE:0
     MODIFIED_COUNTER:1
              AUTOINC:0
            REF_COUNT:1
    

    STATS_INITIALIZED字段指示是否收集了该表的统计信息。 NUM_ROWS是表中当前的估计行数。CLUST_INDEX_SIZEOTHER_INDEX_SIZE场报告后,分别存储集群和二级指标对表在磁盘上的页面数。MODIFIED_COUNTER值显示DML操作修改的行数和外键的级联操作。AUTOINC值是任何基于自动增量操作的下一个数字。在表中没有定义自动增量列t1,所以值为0 REF_COUNT价值是一个计数器。当计数器达到0时,表示表元数据可以从表缓存中逐出。


例14.3外键INFORMATION_SCHEMA系统表

INNODB_SYS_FOREIGNINNODB_SYS_FOREIGN_COLS表格提供了有关外键关系数据。本示例使用具有外键关系的父表和子表来演示在INNODB_SYS_FOREIGNINNODB_SYS_FOREIGN_COLS表中找到的 数据。

  1. 用父表和子表创建测试数据库:

    MySQL的> CREATE DATABASE test;
    
    MySQL的> USE test;
    
    MySQL的> CREATE TABLE parent (id INT NOT NULL,
           PRIMARY KEY (id)) ENGINE=INNODB;
    
    MySQL的> CREATE TABLE child (id INT, parent_id INT,
           INDEX par_ind (parent_id),
           CONSTRAINT fk1
           FOREIGN KEY (parent_id) REFERENCES parent(id)
           ON DELETE CASCADE) ENGINE=INNODB;
    
  2. 创建父和子表后,查询 INNODB_SYS_FOREIGN并定位为外键数据test/childtest/parent外键关系:

    MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN \G
    *************************** 1. row ******************** *******
          ID:test / fk1
    FOR_NAME:测试/孩子
    REF_NAME:测试/父母
      N_COLS:1
        类型:1
    

    元数据包括外键IDfk1),该外键是为CONSTRAINT在子表上定义的名称命名的 FOR_NAME是定义外键的子表的名称。 REF_NAME是父表的名称(引用表)。 N_COLS是外键索引中的列数。TYPE是一个表示位标志的数值,它提供有关外键列的附加信息。在这种情况下, TYPE值为1,这表明 ON DELETE CASCADE选项是为外键指定的。INNODB_SYS_FOREIGN有关TYPE值的更多信息,请参阅 表定义

  3. 使用外键ID查询 INNODB_SYS_FOREIGN_COLS来查看有关外键列的数据。

    MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS WHERE ID = 'test/fk1' \G
    *************************** 1. row ******************** *******
              ID:test / fk1
    FOR_COL_NAME:parent_id
    REF_COL_NAME:ID
             POS:0
    

    FOR_COL_NAME是子表中外键列 REF_COL_NAME的名称,是父表中引用列的名称。POS值是外键索引内的键字段的序号位置,从零开始。


例14.4加入InnoDB INFORMATION_SCHEMA系统表

此示例演示如何连接三个 InnoDB INFORMATION_SCHEMA 系统表(INNODB_SYS_TABLESINNODB_SYS_TABLESPACESINNODB_SYS_TABLESTATS)以收集有关雇员示例数据库中表的文件格式,行格式,页面大小和索引大小信息。

以下表名别名用于缩短查询字符串:

一个IF()控制流功能用于解释压缩的表。如果表格被压缩,则索引大小是使用计算 ZIP_PAGE_SIZE而不是 PAGE_SIZECLUST_INDEX_SIZEOTHER_INDEX_SIZE以字节为单位进行报告,并将其除以1024*1024提供以兆字节(MB)为单位的索引大小。MB值使用该ROUND() 函数四舍五入为零小数空格

MySQL的> SELECT a.NAME, a.FILE_FORMAT, a.ROW_FORMAT,
        @page_size :=
         IF(a.ROW_FORMAT='Compressed',
          b.ZIP_PAGE_SIZE, b.PAGE_SIZE)
          AS page_size,
         ROUND((@page_size * c.CLUST_INDEX_SIZE)
          /(1024*1024)) AS pk_mb,
         ROUND((@page_size * c.OTHER_INDEX_SIZE)
          /(1024*1024)) AS secidx_mb
       FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES a
       INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES b on a.NAME = b.NAME
       INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS c on b.NAME = c.NAME
       WHERE a.NAME LIKE 'employees/%'
       ORDER BY a.NAME DESC;
+ ------------------------ + ------------- + ---------- -  + ----------- + ------- + ----------- +
| NAME | FILE_FORMAT | ROW_FORMAT | page_size | pk_mb | secidx_mb |
+ ------------------------ + ------------- + ---------- -  + ----------- + ------- + ----------- +
| 员工/职位| 羚羊| 紧凑| 16384 | 20 | 11 |
| 员工/薪水| 羚羊| 紧凑| 16384 | 91 | 33 |
| 员工/员工| 羚羊| 紧凑| 16384 | 15 | 0 |
| employees / dept_manager | 羚羊| 紧凑| 16384 | 0 | 0 |
| employees / dept_emp | 羚羊| 紧凑| 16384 | 12 | 10 |
| 员工/部门| 羚羊| 紧凑| 16384 | 0 | 0 |
+ ------------------------ + ------------- + ---------- -  + ----------- + ------- + ----------- +

14.15.4 InnoDB INFORMATION_SCHEMA FULLTEXT索引表

随着在MySQL 5.6.4中引入FULLTEXTInnoDB索引支持,下列表格被添加到INFORMATION_SCHEMA 数据库中:

MySQL的> SHOW TABLES FROM INFORMATION_SCHEMA LIKE 'INNODB_FT%';
+ ------------------------------------------- +
| Tables_in_INFORMATION_SCHEMA(INNODB_FT%)|
+ ------------------------------------------- +
| INNODB_FT_CONFIG |
| INNODB_FT_BEING_DELETED |
| INNODB_FT_DELETED |
| INNODB_FT_DEFAULT_STOPWORD |
| INNODB_FT_INDEX_TABLE |
| INNODB_FT_INDEX_CACHE |
+ ------------------------------------------- +

表概述

注意

INNODB_FT_DEFAULT_STOPWORD表格之外,您必须将innodb_ft_aux_table 配置变量设置为 包含索引的表格(database_name/ table_name的名称FULLTEXT否则,InnoDB FULLTEXT索引 INFORMATION_SCHEMA表显示为空。

例14.5 InnoDB FULLTEXT索引INFORMATION_SCHEMA表

本示例使用带FULLTEXT 索引的表来演示FULLTEXT索引 INFORMATION_SCHEMA表中包含的 数据。

  1. 用a创建一个表 FULLTEXT索引并插入一些数据:

    MySQL的> CREATE TABLE articles (
           id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
           title VARCHAR(200),
           body TEXT,
           FULLTEXT (title,body)
           ) ENGINE=InnoDB;
    
    MySQL的> INSERT INTO articles (title,body) VALUES
           ('MySQL Tutorial','DBMS stands for DataBase ...'),
           ('How To Use MySQL Well','After you went through a ...'),
           ('Optimizing MySQL','In this tutorial we will show ...'),
           ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
           ('MySQL vs. YourSQL','In the following database comparison ...'),
           ('MySQL Security','When configured properly, MySQL ...');
    
  2. innodb_ft_aux_table 变量设置为具有FULLTEXT索引的表的名称 如果未设置此变量,则InnoDB FULLTEXT INFORMATION_SCHEMA表格显示为空,但 INNODB_FT_DEFAULT_STOPWORD 表格

    SET GLOBAL innodb_ft_aux_table ='test / articles';
    
  3. 查询INNODB_FT_INDEX_CACHE 表格,该表格显示有关FULLTEXT索引中新插入行的信息为避免在DML操作期间进行昂贵的索引重组,FULLTEXT 直到OPTIMIZE TABLE运行(或直到服务器关闭或超出缓存限制)时,新插入的行的数据才会保留在索引缓存中

    MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE LIMIT 5;
    + ------------ + -------------- + ------------- + ------- ---- + -------- + ---------- +
    | WORD | FIRST_DOC_ID | LAST_DOC_ID | DOC_COUNT | DOC_ID | 位置|
    + ------------ + -------------- + ------------- + ------- ---- + -------- + ---------- +
    | 1001 | 5 | 5 | 1 | 5 | 0 |
    | 之后| 3 | 3 | 1 | 3 | 22 |
    | 比较| 6 | 6 | 1 | 6 | 44 |
    | 配置为| 7 | 7 | 1 | 7 | 20 |
    | 数据库| 2 | 6 | 2 | 2 | 31 |
    + ------------ + -------------- + ------------- + ------- ---- + -------- + ---------- +
    
  4. 启用 innodb_optimize_fulltext_onlyOPTIMIZE TABLE在包含FULLTEXT索引的表上运行此操作将FULLTEXT索引缓存的内容刷新 到主 FULLTEXT索引。 innodb_optimize_fulltext_only 改变OPTIMIZE TABLE语句在InnoDB表格上的操作 方式,并打算在使用InnoDB表格 进行维护操作期间暂时启用 FULLTEXT索引的

    MySQL的> SET GLOBAL innodb_optimize_fulltext_only=ON;
    查询OK,0行受影响(0.00秒)
    
    MySQL的> OPTIMIZE TABLE articles;
    + --------------- + ---------- + ---------- + ---------- +
    | 表| 操作| Msg_type | Msg_text |
    + --------------- + ---------- + ---------- + ---------- +
    | test.articles | 优化| 状态| 好的|
    + --------------- + ---------- + ---------- + ---------- +
    
  5. 查询INNODB_FT_INDEX_TABLE 表以查看主 FULLTEXT索引中的数据信息,包括刚刚从FULLTEXT索引缓存刷新的数据信息

    MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE LIMIT 5;
    + ------------ + -------------- + ------------- + ------- ---- + -------- + ---------- +
    | WORD | FIRST_DOC_ID | LAST_DOC_ID | DOC_COUNT | DOC_ID | 位置|
    + ------------ + -------------- + ------------- + ------- ---- + -------- + ---------- +
    | 1001 | 5 | 5 | 1 | 5 | 0 |
    | 之后| 3 | 3 | 1 | 3 | 22 |
    | 比较| 6 | 6 | 1 | 6 | 44 |
    | 配置为| 7 | 7 | 1 | 7 | 20 |
    | 数据库| 2 | 6 | 2 | 2 | 31 |
    + ------------ + -------------- + ------------- + ------- ---- + -------- + ---------- +
    

    INNODB_FT_INDEX_CACHE表格现在是空的,因为OPTIMIZE TABLE操作刷新了 FULLTEXT索引缓存

    MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE LIMIT 5;
    空集(0.00秒)
    
  6. test/articles表中删除一些记录

    MySQL的> DELETE FROM test.articles WHERE id < 4;
    查询OK,3行受影响(0.11秒)
    
  7. 查询INNODB_FT_DELETED 表格。该表记录从FULLTEXT索引中删除的行 为避免在DML操作过程中进行昂贵的索引重组,有关新删除记录的信息将单独存储,当您执行文本搜索时会从搜索结果中过滤掉,并在运行时从主搜索索引中删除 OPTIMIZE TABLE

    MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_DELETED;
    + -------- +
    | DOC_ID |
    + -------- +
    | 2 |
    | 3 |
    | 4 |
    + -------- +
    
  8. 运行OPTIMIZE TABLE删除已删除的记录。

    MySQL的> OPTIMIZE TABLE articles;
    + --------------- + ---------- + ---------- + ---------- +
    | 表| 操作| Msg_type | Msg_text |
    + --------------- + ---------- + ---------- + ---------- +
    | test.articles | 优化| 状态| 好的|
    + --------------- + ---------- + ---------- + ---------- +
    

    INNODB_FT_DELETED表现在应该显示为空。

    MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_DELETED;
    空集(0.00秒)
    
  9. 查询INNODB_FT_CONFIG 表格。此表包含有关FULLTEXT索引和相关处理的元数据

    • optimize_checkpoint_limitOPTIMIZE TABLE运行停止后的秒数

    • synced_doc_id是下一个 DOC_ID要发布的。

    • stopword_table_namedatabase/table用户定义的停用词表名称。如果没有用户定义的停用词表,该栏位显示为空。

    • use_stopword指示是否使用停用词表,该表是在FULLTEXT索引创建时定义的

    MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_CONFIG;
    + --------------------------- + ------- +
    | KEY | VALUE |
    + --------------------------- + ------- +
    | optimize_checkpoint_limit | 180 |
    | synced_doc_id | 8 |
    | stopword_table_name | |
    | use_stopword | 1 |
    + --------------------------- + ------- +
    

14.15.5 InnoDB INFORMATION_SCHEMA缓冲池表

InnoDB INFORMATION_SCHEMA缓冲池表提供了有关内页缓冲池的状态信息和元数据InnoDB缓冲池。这些表格在MySQL 5.6.2中引入,后来被移植到MySQL 5.5(在MySQL 5.5.28中)和MySQL 5.1(在MySQL 5.1.66中)。

InnoDB INFORMATION_SCHEMA缓冲池表包括那些列举如下:

MySQL的> SHOW TABLES FROM INFORMATION_SCHEMA LIKE 'INNODB_BUFFER%';
+ ----------------------------------------------- +
| Tables_in_INFORMATION_SCHEMA(INNODB_BUFFER%)|
+ ----------------------------------------------- +
| INNODB_BUFFER_PAGE_LRU |
| INNODB_BUFFER_PAGE |
| INNODB_BUFFER_POOL_STATS |
+ ----------------------------------------------- +

表概述

警告

查询INNODB_BUFFER_PAGE 表或INNODB_BUFFER_PAGE_LRU 表可能会导致显着的性能开销。不要在生产系统上查询这些表,除非您知道您的查询可能具有的性能影响,并且已经确定它是可接受的。为避免影响性能,请重新创建要在测试实例上调查的问题,并在测试实例上运行查询。

例14.6查询INNODB_BUFFER_PAGE表中的系统数据

该查询通过排除表TABLE_NAME值中 NULL包含斜线/ 或句点的页面.(该表格指定用户定义的表格)来提供包含系统数据的近似页数

MySQL的> SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
       WHERE TABLE_NAME IS NULL OR (INSTR(TABLE_NAME, '/') = 0 AND INSTR(TABLE_NAME, '.') = 0);
+ ---------- +
| COUNT(*)|
+ ---------- +
| 1516 |
+ ---------- +

该查询返回包含系统数据的近似页数,缓冲池页面总数以及包含系统数据的页面的近似百分比。

MySQL的> SELECT
       (SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
       WHERE TABLE_NAME IS NULL OR (INSTR(TABLE_NAME, '/') = 0 AND INSTR(TABLE_NAME, '.') = 0)
       ) AS system_pages,
       (
       SELECT COUNT(*)
       FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
       ) AS total_pages,
       (
       SELECT ROUND((system_pages/total_pages) * 100)
       ) AS system_page_percentage;
+ -------------- + ------------- + -------------------- ---- +
| system_pages | total_pages | system_page_percentage |
+ -------------- + ------------- + -------------------- ---- +
| 295 | 8192 | 4 |
+ -------------- + ------------- + -------------------- ---- +

通过查询该PAGE_TYPE可以确定缓冲池中的系统数据类型例如,以下查询将返回PAGE_TYPE包含系统数据的页面中的八个不同 值:

MySQL的> SELECT DISTINCT PAGE_TYPE FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
       WHERE TABLE_NAME IS NULL OR (INSTR(TABLE_NAME, '/') = 0 AND INSTR(TABLE_NAME, '.') = 0);
+ ------------------- +
| PAGE_TYPE |
+ ------------------- +
| SYSTEM |
| IBUF_BITMAP |
| UNKNOWN |
| FILE_SPACE_HEADER |
| INODE |
| UNDO_LOG |
| ALLOCATED |
+ ------------------- +

例14.7查询INNODB_BUFFER_PAGE表中的用户数据

此查询提供的通过其中的计数页面包含用户数据的页的近似计数 TABLE_NAME值为NOT NULLNOT LIKE '%INNODB_SYS_TABLES%'

MySQL的> SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
       WHERE TABLE_NAME IS NOT NULL AND TABLE_NAME NOT LIKE '%INNODB_SYS_TABLES%';
+ ---------- +
| COUNT(*)|
+ ---------- +
| 7897 |
+ ---------- +

此查询返回包含用户数据的大概页数,缓冲池页面的总数以及包含用户数据的页面的近似百分比。

MySQL的> SELECT
       (SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
       WHERE TABLE_NAME IS NOT NULL AND (INSTR(TABLE_NAME, '/') > 0 OR INSTR(TABLE_NAME, '.') > 0)
       ) AS user_pages,
       (
       SELECT COUNT(*)
       FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
       ) AS total_pages,
       (
       SELECT ROUND((user_pages/total_pages) * 100)
       ) AS user_page_percentage;
+ ------------ + ------------- + ---------------------- +
| user_pages | total_pages | user_page_percentage |
+ ------------ + ------------- + ---------------------- +
| 7897 | 8192 | 96 |
+ ------------ + ------------- + ---------------------- +

此查询使用缓冲池中的页面标识用户定义的表格:

MySQL的> SELECT DISTINCT TABLE_NAME FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
       WHERE TABLE_NAME IS NOT NULL AND (INSTR(TABLE_NAME, '/') > 0 OR INSTR(TABLE_NAME, '.') > 0)
       AND TABLE_NAME NOT LIKE '`mysql`.`innodb_%';
+ ------------------------- +
| TABLE_NAME |
+ ------------------------- +
| `雇员`.`slaries` |
| `雇员`.`雇员`|
+ ------------------------- +

例14.8查询INNODB_BUFFER_PAGE表中的索引数据

有关索引页的信息,请INDEX_NAME使用索引名称查询 列。例如,以下查询返回表中emp_no定义索引 的页面数和页面总数据大小 employees.salaries

MySQL的> SELECT INDEX_NAME, COUNT(*) AS Pages,
       ROUND(SUM(IF(COMPRESSED_SIZE = 0, @@global.innodb_page_size, COMPRESSED_SIZE))/1024/1024)
       AS 'Total Data (MB)'
       FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
       WHERE INDEX_NAME='emp_no' AND TABLE_NAME = '`employees`.`salaries`';
+ ------------ + ------- + ----------------- +
| INDEX_NAME | 页面| 总数据(MB)|
+ ------------ + ------- + ----------------- +
| emp_no | 1609 | 25 |
+ ------------ + ------- + ----------------- +

此查询返回employees.salaries表中定义的所有索引的页面数和页面总数据大小

MySQL的> SELECT INDEX_NAME, COUNT(*) AS Pages,
       ROUND(SUM(IF(COMPRESSED_SIZE = 0, @@global.innodb_page_size, COMPRESSED_SIZE))/1024/1024)
       AS 'Total Data (MB)'
       FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
       WHERE TABLE_NAME = '`employees`.`salaries`'
       GROUP BY INDEX_NAME;
+ ------------ + ------- + ----------------- +
| INDEX_NAME | 页面| 总数据(MB)|
+ ------------ + ------- + ----------------- +
| emp_no | 1608 | 25 |
| PRIMARY | 6086 | 95 |
+ ------------ + ------- + ----------------- +

例14.9查询INNODB_BUFFER_PAGE_LRU表中的LRU_POSITION数据

INNODB_BUFFER_PAGE_LRU表保存关于InnoDB缓冲池中的页面的信息 ,特别是如何排序它们以确定当缓冲池变满时哪些页面要从缓冲池中逐出。这个页面的定义与for相同INNODB_BUFFER_PAGE,除了这个表格有一LRU_POSITION列而不是一BLOCK_ID列。

此查询计算employees.employees表中页面占用的LRU列表中特定位置的位置数

MySQL的> SELECT COUNT(LRU_POSITION) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU
       WHERE TABLE_NAME='`employees`.`employees`' AND LRU_POSITION < 3072;
+ --------------------- +
| COUNT(LRU_POSITION)|
+ --------------------- +
| 548 |
+ --------------------- +

例14.10查询INNODB_BUFFER_POOL_STATS表

INNODB_BUFFER_POOL_STATS表提供了类似的信息 SHOW ENGINE INNODB STATUSInnoDB缓冲池的状态变量。

MySQL的> SELECT * FROM information_schema.INNODB_BUFFER_POOL_STATS \G
*************************** 1. row ******************** *******
                         POOL_ID:0
                       POOL_SIZE:8192
                    FREE_BUFFERS:1
                  DATABASE_PAGES:8173
              OLD_DATABASE_PAGES:3014
         MODIFIED_DATABASE_PAGES:0
              PENDING_DECOMPRESS:0
                   PENDING_READS:0
               PENDING_FLUSH_LRU:0
              PENDING_FLUSH_LIST:0
                PAGES_MADE_YOUNG:15907
            PAGES_NOT_MADE_YOUNG:3803101
           PAGES_MADE_YOUNG_RATE:0
       PAGES_MADE_NOT_YOUNG_RATE:0
               NUMBER_PAGES_READ:3270
            NUMBER_PAGES_CREATED:13176
            NUMBER_PAGES_WRITTEN:15109
                 PAGES_READ_RATE:0
               PAGES_CREATE_RATE:0
              PAGES_WRITTEN_RATE:0
                NUMBER_PAGES_GET:33069332
                        HIT_RATE:0
    YOUNG_MAKE_PER_THOUSAND_GETS:0
NOT_YOUNG_MAKE_PER_THOUSAND_GETS:0
         NUMBER_PAGES_READ_AHEAD:2713
       NUMBER_READ_AHEAD_EVICTED:0
                 READ_AHEAD_RATE:0
         READ_AHEAD_EVICTED_RATE:0
                    LRU_IO_TOTAL:0
                  LRU_IO_CURRENT:0
                UNCOMPRESS_TOTAL:0
              UNCOMPRESS_CURRENT:0

作为比较, SHOW ENGINE INNODB STATUS输出和InnoDB缓冲池状态变量输出如下所示,基于相同的数据集。

有关SHOW ENGINE INNODB STATUS输出的更多信息 ,请参见 第14.17.3节“InnoDB标准监视器和锁定监视器输出”

MySQL的> SHOW ENGINE INNODB STATUS \G
...
----------------------
缓冲池和内存
----------------------
总大内存分配137428992
分配的字典内存579084
缓冲池大小8192
免费缓冲区1
数据库页面8173
旧的数据库页面3014
修改数据库页面0
等待读取0
等待写入:LRU 0,刷新列表0,单个页面0
年轻的书15907,而不是年轻的3803101
0.00青少年/秒,0.00非青少年/秒
页面读取3270,创建13176,写入15109
0.00读/秒,0.00创建/秒,0.00写/秒
自上次打印输出以来没有获得缓冲池页面
提前读取的页数为0.00 /秒,不带访问时驱逐为0.00 /秒,随机读取为0.00 /秒
LRU len:8173,unzip_LRU len:0
I / O sum [0]:cur [0],unzip sum [0]:cur [0]
...

有关状态变量说明,请参见 第5.1.7节“服务器状态变量”

MySQL的> SHOW STATUS LIKE 'Innodb_buffer%';
+ --------------------------------------- + --------- ---- +
| 变量名| 值|
+ --------------------------------------- + --------- ---- +
| Innodb_buffer_pool_dump_status | 没有开始|
| Innodb_buffer_pool_load_status | 没有开始|
| Innodb_buffer_pool_resize_status | 没有开始|
| Innodb_buffer_pool_pages_data | 8173 |
| Innodb_buffer_pool_bytes_data | 133906432 |
| Innodb_buffer_pool_pages_dirty | 0 |
| Innodb_buffer_pool_bytes_dirty | 0 |
| Innodb_buffer_pool_pages_flushed | 15109 |
| Innodb_buffer_pool_pages_free | 1 |
| Innodb_buffer_pool_pages_misc | 18 |
| Innodb_buffer_pool_pages_total | 8192 |
| Innodb_buffer_pool_read_ahead_rnd | 0 |
| Innodb_buffer_pool_read_ahead | 2713 |
| Innodb_buffer_pool_read_ahead_evicted | 0 |
| Innodb_buffer_pool_read_requests | 33069332 |
| Innodb_buffer_pool_reads | 558 |
| Innodb_buffer_pool_wait_free | 0 |
| Innodb_buffer_pool_write_requests | 11985961 |
+ --------------------------------------- + --------- ---- +

14.15.6 InnoDB INFORMATION_SCHEMA度量表

INNODB_METRICS表在MySQL 5.6.2中引入,将所有InnoDB 性能和资源相关的计数器合并到一个 INFORMATION_SCHEMA表中。

INNODB_METRICS 以下示例中显示 了该的列有关每列的说明,请参见第24.31.15节“INFORMATION_SCHEMA INNODB_METRICS表”

MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME="dml_inserts" \G
*************************** 1. row ******************** *******
           名称:dml_inserts
      SUBSYSTEM:dml
          COUNT:46273
      MAX_COUNT:46273
      MIN_COUNT:NULL
      AVG_COUNT:492.2659574468085
    COUNT_RESET:46273
MAX_COUNT_RESET:46273
MIN_COUNT_RESET:NULL
AVG_COUNT_RESET:NULL
   TIME_ENABLED:2014-11-28 16:07:53
  TIME_DISABLED:NULL
   TIME_ELAPSED:94
     TIME_RESET:NULL
         状态:启用
           TYPE:status_counter
        注释:插入的行数

启用,禁用和重置计数器

您可以使用以下配置选项启用,禁用和重置计数器:

  • innodb_monitor_enable:启用一个或多个计数器。

    SET GLOBAL innodb_monitor_enable = [counter-name | module_name | pattern | all];
    
  • innodb_monitor_disable:禁用一个或多个计数器。

    SET GLOBAL innodb_monitor_disable = [counter-name | module_name | pattern | all];
    
  • innodb_monitor_reset:将一个或多个计数器的计数值重置为零。

    SET GLOBAL innodb_monitor_reset = [counter-name | module_name | pattern | all];
    
  • innodb_monitor_reset_all:重置一个或多个计数器的所有值。使用前必须禁用计数器 innodb_monitor_reset_all

    SET GLOBAL innodb_monitor_reset_all = [counter-name | module_name | pattern | all];
    

您也可以在启动时使用MySQL服务器配置文件启用计数器和计数器模块。例如,要启用 log模块 metadata_table_handles_openedmetadata_table_handles_closed计数器,请在配置文件[mysqld]部分中输入以下行my.cnf

的[mysqld]
innodb_monitor_enable = module_recovery,metadata_table_handles_opened,metadata_table_handles_closed

在配置文件中启用多个计数器或模块时,必须指定innodb_monitor_enable 配置选项,然后指定 用逗号分隔的计数器和模块名称,如上例所示。只有innodb_monitor_enable您的配置文件中可以使用选项。禁用和重置配置选项仅在命令行上受支持。

注意

由于每个计数器都会在服务器上产生一定程度的运行时间开销,因此通常在实验和基准测试期间在测试和开发服务器上启用更多计数器,并且只启用生产服务器上的计数器来诊断已知问题或监视可能成为瓶颈的方面特定服务器和工作量。

计数器

INNODB_METRICS表中 的计数器 可能会发生变化,所以对于最新的列表,查询正在运行的MySQL服务器。

默认启用的计数器对应于那些使用的计数器 SHOW ENGINE INNODB STATUS所使用的计数器 在系统级别SHOW ENGINE INNODB STATUS始终处于打开 ”状态,但可以INNODB_METRICS根据需要禁用这些计数器 此外,计数器状态不是持久的。除非另行指定,否则计数器将在服务器重新启动时恢复为其默认启用或禁用状态。

如果您运行的程序受到INNODB_METRICS表格添加或更改的影响,建议您INNODB_METRICS在升级之前查看发行说明并在新版本中查询 表格。

MySQL的> SELECT name, subsystem, status FROM INFORMATION_SCHEMA.INNODB_METRICS ORDER BY NAME;
------------------------------------------ + ------ + --------------- + ---------- +
| 名称| 子系统| 状态|
------------------------------------------ + ------ + --------------- + ---------- +
| adaptive_hash_pages_added | adaptive_hash_index | 禁用|
| adaptive_hash_pages_removed | adaptive_hash_index | 禁用|
| adaptive_hash_rows_added | adaptive_hash_index | 禁用|
| adaptive_hash_rows_deleted_no_hash_entry | adaptive_hash_index | 禁用|
| adaptive_hash_rows_removed | adaptive_hash_index | 禁用|
| adaptive_hash_rows_updated | adaptive_hash_index | 禁用|
| adaptive_hash_searches | adaptive_hash_index | 启用|
| adaptive_hash_searches_btree | adaptive_hash_index | 启用|
| buffer_data_reads | 缓冲区| 启用|
| buffer_data_written | 缓冲区| 启用|
| buffer_flush_adaptive | 缓冲区| 禁用|
| buffer_flush_adaptive_avg_pass | 缓冲区| 禁用|
| buffer_flush_adaptive_avg_time_est | 缓冲区| 禁用|
| buffer_flush_adaptive_avg_time_slot | 缓冲区| 禁用|
| buffer_flush_adaptive_avg_time_thread | 缓冲区| 禁用|
| buffer_flush_adaptive_pages | 缓冲区| 禁用|
| buffer_flush_adaptive_total_pages | 缓冲区| 禁用|
| buffer_flush_avg_page_rate | 缓冲区| 禁用|
| buffer_flush_avg_pass | 缓冲区| 禁用|
| buffer_flush_avg_time | 缓冲区| 禁用|
| buffer_flush_background | 缓冲区| 禁用|
| buffer_flush_background_pages | 缓冲区| 禁用|
| buffer_flush_background_total_pages | 缓冲区| 禁用|
| buffer_flush_batches | 缓冲区| 禁用|
| buffer_flush_batch_num_scan | 缓冲区| 禁用|
| buffer_flush_batch_pages | 缓冲区| 禁用|
| buffer_flush_batch_scanned | 缓冲区| 禁用|
| buffer_flush_batch_scanned_per_call | 缓冲区| 禁用|
| buffer_flush_batch_total_pages | 缓冲区| 禁用|
| buffer_flush_lsn_avg_rate | 缓冲区| 禁用|
| buffer_flush_neighbor | 缓冲区| 禁用|
| buffer_flush_neighbor_pages | 缓冲区| 禁用|
| buffer_flush_neighbor_total_pages | 缓冲区| 禁用|
| buffer_flush_n_to_flush_by_age | 缓冲区| 禁用|
| buffer_flush_n_to_flush_requested | 缓冲区| 禁用|
| buffer_flush_pct_for_dirty | 缓冲区| 禁用|
| buffer_flush_pct_for_lsn | 缓冲区| 禁用|
| buffer_flush_sync | 缓冲区| 禁用|
| buffer_flush_sync_pages | 缓冲区| 禁用|
| buffer_flush_sync_total_pages | 缓冲区| 禁用|
| buffer_flush_sync_waits | 缓冲区| 禁用|
| buffer_LRU_batches_evict | 缓冲区| 禁用|
| buffer_LRU_batches_flush | 缓冲区| 禁用|
| buffer_LRU_batch_evict_pages | 缓冲区| 禁用|
| buffer_LRU_batch_evict_total_pages | 缓冲区| 禁用|
| buffer_LRU_batch_flush_avg_pass | 缓冲区| 禁用|
| buffer_LRU_batch_flush_avg_time_est | 缓冲区| 禁用|
| buffer_LRU_batch_flush_avg_time_slot | 缓冲区| 禁用|
| buffer_LRU_batch_flush_avg_time_thread | 缓冲区| 禁用|
| buffer_LRU_batch_flush_pages | 缓冲区| 禁用|
| buffer_LRU_batch_flush_total_pages | 缓冲区| 禁用|
| buffer_LRU_batch_num_scan | 缓冲区| 禁用|
| buffer_LRU_batch_scanned | 缓冲区| 禁用|
| buffer_LRU_batch_scanned_per_call | 缓冲区| 禁用|
| buffer_LRU_get_free_loops | 缓冲区| 禁用|
| buffer_LRU_get_free_search | 缓冲区| 禁用|
| buffer_LRU_get_free_waits | 缓冲区| 禁用|
| buffer_LRU_search_num_scan | 缓冲区| 禁用|
| buffer_LRU_search_scanned | 缓冲区| 禁用|
| buffer_LRU_search_scanned_per_call | 缓冲区| 禁用|
| buffer_LRU_single_flush_failure_count | 缓冲区| 禁用|
| buffer_LRU_single_flush_num_scan | 缓冲区| 禁用|
| buffer_LRU_single_flush_scanned | 缓冲区| 禁用|
| buffer_LRU_single_flush_scanned_per_call | 缓冲区| 禁用|
| buffer_LRU_unzip_search_num_scan | 缓冲区| 禁用|
| buffer_LRU_unzip_search_scanned | 缓冲区| 禁用|
| buffer_LRU_unzip_search_scanned_per_call | 缓冲区| 禁用|
| buffer_pages_created | 缓冲区| 启用|
| buffer_pages_read | 缓冲区| 启用|
| buffer_pages_written | 缓冲区| 启用|
| buffer_page_read_blob | buffer_page_io | 禁用|
| buffer_page_read_fsp_hdr | buffer_page_io | 禁用|
| buffer_page_read_ibuf_bitmap | buffer_page_io | 禁用|
| buffer_page_read_ibuf_free_list | buffer_page_io | 禁用|
| buffer_page_read_index_ibuf_leaf | buffer_page_io | 禁用|
| buffer_page_read_index_ibuf_non_leaf | buffer_page_io | 禁用|
| buffer_page_read_index_inode | buffer_page_io | 禁用|
| buffer_page_read_index_leaf | buffer_page_io | 禁用|
| buffer_page_read_index_non_leaf | buffer_page_io | 禁用|
| buffer_page_read_other | buffer_page_io | 禁用|
| buffer_page_read_system_page | buffer_page_io | 禁用|
| buffer_page_read_trx_system | buffer_page_io | 禁用|
| buffer_page_read_undo_log | buffer_page_io | 禁用|
| buffer_page_read_xdes | buffer_page_io | 禁用|
| buffer_page_read_zblob | buffer_page_io | 禁用|
| buffer_page_read_zblob2 | buffer_page_io | 禁用|
| buffer_page_written_blob | buffer_page_io | 禁用|
| buffer_page_written_fsp_hdr | buffer_page_io | 禁用|
| buffer_page_written_ibuf_bitmap | buffer_page_io | 禁用|
| buffer_page_written_ibuf_free_list | buffer_page_io | 禁用|
| buffer_page_written_index_ibuf_leaf | buffer_page_io | 禁用|
| buffer_page_written_index_ibuf_non_leaf | buffer_page_io | 禁用|
| buffer_page_written_index_inode | buffer_page_io | 禁用|
| buffer_page_written_index_leaf | buffer_page_io | 禁用|
| buffer_page_written_index_non_leaf | buffer_page_io | 禁用|
| buffer_page_written_other | buffer_page_io | 禁用|
| buffer_page_written_system_page | buffer_page_io | 禁用|
| buffer_page_written_trx_system | buffer_page_io | 禁用|
| buffer_page_written_undo_log | buffer_page_io | 禁用|
| buffer_page_written_xdes | buffer_page_io | 禁用|
| buffer_page_written_zblob | buffer_page_io | 禁用|
| buffer_page_written_zblob2 | buffer_page_io | 禁用|
| buffer_pool_bytes_data | 缓冲区| 启用|
| buffer_pool_bytes_dirty | 缓冲区| 启用|
| buffer_pool_pages_data | 缓冲区| 启用|
| buffer_pool_pages_dirty | 缓冲区| 启用|
| buffer_pool_pages_free | 缓冲区| 启用|
| buffer_pool_pages_misc | 缓冲区| 启用|
| buffer_pool_pages_total | 缓冲区| 启用|
| buffer_pool_reads | 缓冲区| 启用|
| buffer_pool_read_ahead | 缓冲区| 启用|
| buffer_pool_read_ahead_evicted | 缓冲区| 启用|
| buffer_pool_read_requests | 缓冲区| 启用|
| buffer_pool_size | 服务器| 启用|
| buffer_pool_wait_free | 缓冲区| 启用|
| buffer_pool_write_requests | 缓冲区| 启用|
| compression_pad_decrements | 压缩| 禁用|
| compression_pad_increments | 压缩| 禁用|
| compress_pages_compressed | 压缩| 禁用|
| compress_pages_decompressed | 压缩| 禁用|
| ddl_background_drop_indexes | ddl | 禁用|
| ddl_background_drop_tables | ddl | 禁用|
| ddl_log_file_alter_table | ddl | 禁用|
| ddl_online_create_index | ddl | 禁用|
| ddl_pending_alter_table | ddl | 禁用|
| ddl_sort_file_alter_table | ddl | 禁用|
| dml_deletes | dml | 启用|
| dml_inserts | dml | 启用|
| dml_reads | dml | 禁用|
| dml_updates | dml | 启用|
| file_num_open_files | file_system | 启用|
| ibuf_merges | change_buffer | 启用|
| ibuf_merges_delete | change_buffer | 启用|
| ibuf_merges_delete_mark | change_buffer | 启用|
| ibuf_merges_discard_delete | change_buffer | 启用|
| ibuf_merges_discard_delete_mark | change_buffer | 启用|
| ibuf_merges_discard_insert | change_buffer | 启用|
| ibuf_merges_insert | change_buffer | 启用|
| ibuf_size | change_buffer | 启用|
| icp_attempts | icp | 禁用|
| icp_match | icp | 禁用|
| icp_no_match | icp | 禁用|
| icp_out_of_range | icp | 禁用|
| index_page_discards | 索引| 禁用|
| index_page_merge_attempts | 索引| 禁用|
| index_page_merge_successful | 索引| 禁用|
| index_page_reorg_attempts | 索引| 禁用|
| index_page_reorg_successful | 索引| 禁用|
| index_page_splits | 索引| 禁用|
| innodb_activity_count | 服务器| 启用|
| innodb_background_drop_table_usec | 服务器| 禁用|
| innodb_checkpoint_usec | 服务器| 禁用|
| innodb_dblwr_pages_written | 服务器| 启用|
| innodb_dblwr_writes | 服务器| 启用|
| innodb_dict_lru_count | 服务器| 禁用|
| innodb_dict_lru_usec | 服务器| 禁用|
| innodb_ibuf_merge_usec | 服务器| 禁用|
| innodb_log_flush_usec | 服务器| 禁用|
| innodb_master_active_loops | 服务器| 禁用|
| innodb_master_idle_loops | 服务器| 禁用|
| innodb_master_purge_usec | 服务器| 禁用|
| innodb_master_thread_sleeps | 服务器| 禁用|
| innodb_mem_validate_usec | 服务器| 禁用|
| innodb_page_size | 服务器| 启用|
| innodb_rwlock_sx_os_waits | 服务器| 启用|
| innodb_rwlock_sx_spin_rounds | 服务器| 启用|
| innodb_rwlock_sx_spin_waits | 服务器| 启用|
| innodb_rwlock_s_os_waits | 服务器| 启用|
| innodb_rwlock_s_spin_rounds | 服务器| 启用|
| innodb_rwlock_s_spin_waits | 服务器| 启用|
| innodb_rwlock_x_os_waits | 服务器| 启用|
| innodb_rwlock_x_spin_rounds | 服务器| 启用|
| innodb_rwlock_x_spin_waits | 服务器| 启用|
| lock_deadlocks | 锁定| 启用|
| lock_rec_locks | 锁定| 禁用|
| lock_rec_lock_created | 锁定| 禁用|
| lock_rec_lock_removed | 锁定| 禁用|
| lock_rec_lock_requests | 锁定| 禁用|
| lock_rec_lock_waits | 锁定| 禁用|
| lock_row_lock_current_waits | 锁定| 启用|
| lock_row_lock_time | 锁定| 启用|
| lock_row_lock_time_avg | 锁定| 启用|
| lock_row_lock_time_max | 锁定| 启用|
| lock_row_lock_waits | 锁定| 启用|
| lock_table_locks | 锁定| 禁用|
| lock_table_lock_created | 锁定| 禁用|
| lock_table_lock_removed | 锁定| 禁用|
| lock_table_lock_waits | 锁定| 禁用|
| lock_timeouts | 锁定| 启用|
| log_checkpoints | 恢复| 禁用|
| log_lsn_buf_pool_oldest | 恢复| 禁用|
| log_lsn_checkpoint_age | 恢复| 禁用|
| log_lsn_current | 恢复| 禁用|
| log_lsn_last_checkpoint | 恢复| 禁用|
| log_lsn_last_flush | 恢复| 禁用|
| log_max_modified_age_async | 恢复| 禁用|
| log_max_modified_age_sync | 恢复| 禁用|
| log_num_log_io | 恢复| 禁用|
| log_padded | 恢复| 启用|
| log_pending_checkpoint_writes | 恢复| 禁用|
| log_pending_log_flushes | 恢复| 禁用|
| log_waits | 恢复| 启用|
| log_writes | 恢复| 启用|
| log_write_requests | 恢复| 启用|
| metadata_table_handles_closed | 元数据| 禁用|
| metadata_table_handles_opened | 元数据| 禁用|
| metadata_table_reference_count | 元数据| 禁用|
| os_data_fsyncs | os | 启用|
| os_data_reads | os | 启用|
| os_data_writes | os | 启用|
| os_log_bytes_written | os | 启用|
| os_log_fsyncs | os | 启用|
| os_log_pending_fsyncs | os | 启用|
| os_log_pending_writes | os | 启用|
| os_pending_reads | os | 禁用|
| os_pending_writes | os | 禁用|
| purge_del_mark_records | 清除| 禁用|
| purge_dml_delay_usec | 清除| 禁用|
| purge_invoked | 清除| 禁用|
| purge_resume_count | 清除| 禁用|
| purge_stop_count | 清除| 禁用|
| purge_undo_log_pages | 清除| 禁用|
| purge_upd_exist_or_extern_records | 清除| 禁用|
| trx_active_transactions | 交易| 禁用|
| trx_commits_insert_update | 交易| 禁用|
| trx_nl_ro_commits | 交易| 禁用|
| trx_rollbacks | 交易| 禁用|
| trx_rollbacks_savepoint | 交易| 禁用|
| trx_rollback_active | 交易| 禁用|
| trx_ro_commits | 交易| 禁用|
| trx_rseg_current_size | 交易| 禁用|
| trx_rseg_history_len | 交易| 启用|
| trx_rw_commits | 交易| 禁用|
| trx_undo_slots_cached | 交易| 禁用|
| trx_undo_slots_used | 交易| 禁用|
------------------------------------------ + ------ + --------------- + ---------- +
一组235行(0.01秒)

计数器模块

模块名称对应于表格SUBSYSTEM列中的 值,但不相同INNODB_METRICS单独启用,禁用或重置计数器,您可以使用模块名称快速启用,禁用或重置特定子系统的所有计数器。例如,用于 module_dml启用与dml子系统关联的所有计数器

MySQL的> SET GLOBAL innodb_monitor_enable = module_dml;

MySQL的> SELECT name, subsystem, status FROM INFORMATION_SCHEMA.INNODB_METRICS
       WHERE subsystem ='dml';
+ ------------- ----------- + + --------- +
| 名称| 子系统| 状态|
+ ------------- ----------- + + --------- +
| dml_reads | dml | 启用|
| dml_inserts | dml | 启用|
| dml_deletes | dml | 启用|
| dml_updates | dml | 启用|
+ ------------- ----------- + + --------- +

下面是可以使用的值 module_nameinnodb_monitor_enable和相关的配置选项,以及相应的一起 SUBSYSTEM名称:

  • module_adaptive_hash(子系统= adaptive_hash_index

  • module_buffer(子系统= buffer

  • module_buffer_page(子系统= buffer_page_io

  • module_compress(子系统= compression

  • module_ddl(子系统= ddl

  • module_dml(子系统= dml

  • module_file(子系统= file_system

  • module_ibuf_system(子系统= change_buffer

  • module_icp(子系统= icp

  • module_index(子系统= index

  • module_innodb(子系统= innodb

  • module_lock(子系统= lock

  • module_log(子系统= recovery

  • module_metadata(子系统= metadata

  • module_os(子系统= os

  • module_purge(子系统= purge

  • module_trx(子系统= transaction

例14.11使用INNODB_METRICS表计数器

此示例演示启用,禁用和重置计数器以及查询INNODB_METRICS表中的计数器数据

  1. 创建一个简单的InnoDB表格:

    MySQL的> USE test;
    数据库改变
    
    MySQL的> CREATE TABLE t1 (c1 INT) ENGINE=INNODB;
    查询OK,0行受影响(0.02秒)
    
  2. 启用dml_inserts计数器。

    MySQL的> SET GLOBAL innodb_monitor_enable = dml_inserts;
    查询OK,0行受影响(0.01秒)
    

    表格栏中 dml_inserts可以找到计数器 的说明COMMENTINNODB_METRICS

    MySQL的> SELECT NAME, COMMENT FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME="dml_inserts";
    + ------------- + ------------------------- +
    | NAME | 评论|
    + ------------- + ------------------------- +
    | dml_inserts | 插入的行数|
    + ------------- + ------------------------- +
    
  3. 查询INNODB_METRICS表格中的dml_inserts计数器数据。由于没有执行DML操作,因此计数器值为零或NULL。TIME_ENABLEDTIME_ELAPSED值表明,当计数器最后一次启用,因为这个时候多少秒的流逝。

    MySQL的>  SELECT * FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME="dml_inserts" \G
    *************************** 1. row ******************** *******
               名称:dml_inserts
          SUBSYSTEM:dml
              COUNT:0
          MAX_COUNT:0
          MIN_COUNT:NULL
          AVG_COUNT:0
        COUNT_RESET:0
    MAX_COUNT_RESET:0
    MIN_COUNT_RESET:NULL
    AVG_COUNT_RESET:NULL
       TIME_ENABLED:2014-12-04 14:18:28
      TIME_DISABLED:NULL
       TIME_ELAPSED:28
         TIME_RESET:NULL
             状态:启用
               TYPE:status_counter
            注释:插入的行数
    
  4. 将三行数据插入表中。

    MySQL的> INSERT INTO t1 values(1);
    查询OK,1行受影响(0.00秒)
    
    MySQL的> INSERT INTO t1 values(2);
    查询OK,1行受影响(0.00秒)
    
    MySQL的> INSERT INTO t1 values(3);
    查询OK,1行受影响(0.00秒)
    
  5. INNODB_METRICS再次 查询表格中的dml_inserts计数器数据。许多计数器值现在已经增加,包括 COUNTMAX_COUNTAVG_COUNT,和 COUNT_RESETINNODB_METRICS有关这些值的说明,请参阅 表格定义。

    MySQL的>  SELECT * FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME="dml_inserts"\G
    *************************** 1. row ******************** *******
               名称:dml_inserts
          SUBSYSTEM:dml
              COUNT:3
          MAX_COUNT:3
          MIN_COUNT:NULL
          AVG_COUNT:0.046153846153846156
        COUNT_RESET:3
    MAX_COUNT_RESET:3
    MIN_COUNT_RESET:NULL
    AVG_COUNT_RESET:NULL
       TIME_ENABLED:2014-12-04 14:18:28
      TIME_DISABLED:NULL
       TIME_ELAPSED:65
         TIME_RESET:NULL
             状态:启用
               TYPE:status_counter
            注释:插入的行数
    
  6. 重置dml_inserts计数器,然后INNODB_METRICS再次查询表格中的dml_inserts计数器数据。%_RESET先前报告值(例如COUNT_RESETMAX_RESET)被设置回零。从启用计数器时累计收集数据的值,如COUNTMAX_COUNTAVG_COUNT,不受重置的影响。

    MySQL的> SET GLOBAL innodb_monitor_reset = dml_inserts;
    查询OK,0行受影响(0.00秒)
    
    MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME="dml_inserts"\G
    *************************** 1. row ******************** *******
               名称:dml_inserts
          SUBSYSTEM:dml
              COUNT:3
          MAX_COUNT:3
          MIN_COUNT:NULL
          AVG_COUNT:0.03529411764705882
        COUNT_RESET:0
    MAX_COUNT_RESET:0
    MIN_COUNT_RESET:NULL
    AVG_COUNT_RESET:0
       TIME_ENABLED:2014-12-04 14:18:28
      TIME_DISABLED:NULL
       TIME_ELAPSED:85
         TIME_RESET:2014-12-04 14:19:44
             状态:启用
               TYPE:status_counter
            注释:插入的行数
    
  7. 要重置所有计数器值,您必须先禁用计数器。禁用计数器将STATUS设置 disbaled

    MySQL的> SET GLOBAL innodb_monitor_disable = dml_inserts;
    查询OK,0行受影响(0.00秒)
    
    MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME="dml_inserts"\G
    *************************** 1. row ******************** *******
               名称:dml_inserts
          SUBSYSTEM:dml
              COUNT:3
          MAX_COUNT:3
          MIN_COUNT:NULL
          AVG_COUNT:0.030612244897959183
        COUNT_RESET:0
    MAX_COUNT_RESET:0
    MIN_COUNT_RESET:NULL
    AVG_COUNT_RESET:0
       TIME_ENABLED:2014-12-04 14:18:28
      TIME_DISABLED:2014-12-04 14:20:06
       TIME_ELAPSED:98
         TIME_RESET:NULL
             状态:已禁用
               TYPE:status_counter
            注释:插入的行数
    
    注意

    计数器和模块名称支持通配符匹配。例如,dml_inserts您可以指定,而不是指定完整的 计数器名称dml_i%您还可以使用通配符匹配一次启用,禁用或重置多个计数器或模块。例如,指定 dml_%启用,禁用或重置所有以开头的计数器dml_%

  8. 计数器被禁用后,您可以使用该innodb_monitor_reset_all 选项重置所有计数器值 所有值都设置为零或NULL。

    MySQL的> SET GLOBAL innodb_monitor_reset_all = dml_inserts;
    查询OK,0行受影响(0.00秒)
     
    MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME="dml_inserts"\G
    *************************** 1. row ******************** *******
               名称:dml_inserts
          SUBSYSTEM:dml
              COUNT:0
          MAX_COUNT:NULL
          MIN_COUNT:NULL
          AVG_COUNT:NULL
        COUNT_RESET:0
    MAX_COUNT_RESET:NULL
    MIN_COUNT_RESET:NULL
    AVG_COUNT_RESET:NULL
       TIME_ENABLED:NULL
      TIME_DISABLED:NULL
       TIME_ELAPSED:NULL
         TIME_RESET:NULL
             状态:已禁用
               TYPE:status_counter
            注释:插入的行数
    

14.15.7 InnoDB INFORMATION_SCHEMA临时表信息表

INNODB_TEMP_TABLE_INFO提供有关InnoDBInnoDB实例中当前活动的用户创建的临时表的 信息它不提供有关InnoDB优化程序使用的内部临时表的信息

MySQL的> SHOW TABLES FROM INFORMATION_SCHEMA LIKE 'INNODB_TEMP%';
+ --------------------------------------------- +
| Tables_in_INFORMATION_SCHEMA(INNODB_TEMP%)|
+ --------------------------------------------- +
| INNODB_TEMP_TABLE_INFO |
+ --------------------------------------------- +

有关表定义,请参见 第24.31.26节“INFORMATION_SCHEMA INNODB_TEMP_TABLE_INFO表”

例14.12 INNODB_TEMP_TABLE_INFO

这个例子演示了INNODB_TEMP_TABLE_INFO表格的特征

  1. 创建一个简单的InnoDB临时表:

    MySQL的> CREATE TEMPORARY TABLE t1 (c1 INT PRIMARY KEY) ENGINE=INNODB;
    
  2. 查询INNODB_TEMP_TABLE_INFO查看临时表元数据。

    MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO\G
    *************************** 1. row ******************** *******
                TABLE_ID:194
                    名称:#sql7a79_1_0
                  N_COLS:4
                   空间:182
    PER_TABLE_TABLESPACE:FALSE
           IS_COMPRESSED:FALSE
    

    TABLE_ID 是临时表的唯一标识符。NAME列显示临时表的系统生成名称,该名称前缀为#sql列(数N_COLS)为4,而不是1,因为InnoDB总是创建三个隐藏的表列(DB_ROW_IDDB_TRX_ID,和 DB_ROLL_PTR)。 PER_TABLE_TABLESPACEIS_COMPRESSED报告 TRUE压缩的临时表。否则,这些字段会报告FALSE

  3. 创建一个压缩的临时表。

    MySQL的> CREATE TEMPORARY TABLE t2 (c1 INT) ROW_FORMAT=COMPRESSED ENGINE=INNODB;
    
  4. INNODB_TEMP_TABLE_INFO 再次 查询

    MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO\G
    *************************** 1. row ******************** *******
                TABLE_ID:195
                    名称:#sql7a79_1_1
                  N_COLS:4
                   空间:183
    PER_TABLE_TABLESPACE:TRUE
           IS_COMPRESSED:TRUE
    *************************** 2. row ******************** *******
                TABLE_ID:194
                    名称:#sql7a79_1_0
                  N_COLS:4
                   空间:182
    PER_TABLE_TABLESPACE:FALSE
           IS_COMPRESSED:FALSE
    

    PER_TABLE_TABLESPACEIS_COMPRESSED报告 TRUE压缩的临时表。SPACE压缩临时表ID不同,因为压缩临时表是在单独的每个表的表空间中创建的。在共享临时表空间(ibtmp1中创建非压缩临时表并报告相同的SPACEID。

  5. 重新启动MySQL并进行查询 INNODB_TEMP_TABLE_INFO

    MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO\G
    空集(0.00秒)
    

    返回一个空集,因为 INNODB_TEMP_TABLE_INFO在服务器关闭时,其中的数据不会持久化到磁盘。

  6. 创建一个新的临时表。

    MySQL的> CREATE TEMPORARY TABLE t1 (c1 INT PRIMARY KEY) ENGINE=INNODB;
    
  7. 查询INNODB_TEMP_TABLE_INFO查看临时表元数据。

    MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO\G
    *************************** 1. row ******************** *******
                TABLE_ID:196
                    NAME:#sql7b0e_1_0
                  N_COLS:4
                   空间:184
    PER_TABLE_TABLESPACE:FALSE
           IS_COMPRESSED:FALSE
    

    SPACEID是新的,因为它是在服务器重新启动时动态生成的。


14.15.8从INFORMATION_SCHEMA.FILES中检索InnoDB表空间元数据

INFORMATION_SCHEMA.FILES表提供有关所有InnoDB表空间类型的元数据,其中包括每个表的文件表空间常规表空间系统表空间临时表空间表撤消表空间(如果存在)。

本节提供了InnoDB特定的使用示例。有关该INFORMATION_SCHEMA.FILES提供的数据的更多信息 ,请参见 第24.8节“INFORMATION_SCHEMA文件表”

注意

所述INNODB_SYS_TABLESPACESINNODB_SYS_DATAFILES表还提供有关的元数据InnoDB的表空间,但数据是仅限于文件每次表和一般的表空间。

此查询InnoDBINFORMATION_SCHEMA.FILES表中与InnoDB表空间相关的字段中检索有关系统表空间的 元数据INFORMATION_SCHEMA.FILESInnoDB总是返回NULL 不相关的字段,并从查询中排除。

MySQL的> SELECT FILE_ID, FILE_NAME, FILE_TYPE, TABLESPACE_NAME, FREE_EXTENTS,
       TOTAL_EXTENTS,  EXTENT_SIZE, INITIAL_SIZE, MAXIMUM_SIZE, AUTOEXTEND_SIZE, DATA_FREE, STATUS ENGINE
       FROM INFORMATION_SCHEMA.FILES WHERE TABLESPACE_NAME LIKE 'innodb_system' \G
*************************** 1. row ******************** *******
        FILE_ID:0
      FILE_NAME:./ibdata1
      FILE_TYPE:TABLESPACE
TABLESPACE_NAME:innodb_system
   FREE_EXTENTS:0
  TOTAL_EXTENTS:12
    EXTENT_SIZE:1048576
   INITIAL_SIZE:12582912
   MAXIMUM_SIZE:NULL
AUTOEXTEND_SIZE:67108864
      DATA_FREE:4194304
         ENGINE:NORMAL

该查询检索文件每表和文件(一般表FILE_ID空间)(等同于空间ID)和FILE_NAME(其中包括路径信息)InnoDB每个表文件和一般表空间都有一个 .ibd文件扩展名。

MySQL的> SELECT FILE_ID, FILE_NAME FROM INFORMATION_SCHEMA.FILES
       WHERE FILE_NAME LIKE '%.ibd%' ORDER BY FILE_ID;
    + --------- + --------------------------------------- +
    | FILE_ID | FILE_NAME |
    + --------- + --------------------------------------- +
    | 2 | ./mysql/plugin.ibd |
    | 3 | ./mysql/servers.ibd |
    | 4 | ./mysql/help_topic.ibd |
    | 5 | ./mysql/help_category.ibd |
    | 6 | ./mysql/help_relation.ibd |
    | 7 | ./mysql/help_keyword.ibd |
    | 8 | ./mysql/time_zone_name.ibd |
    | 9 | ./mysql/time_zone.ibd |
    | 10 | ./mysql/time_zone_transition.ibd |
    | 11 | ./mysql/time_zone_transition_type.ibd |
    | 12 | ./mysql/time_zone_leap_second.ibd |
    | 13 | ./mysql/innodb_table_stats.ibd |
    | 14 | ./mysql/innodb_index_stats.ibd |
    | 15 | ./mysql/slave_relay_log_info.ibd |
    | 16 | ./mysql/slave_master_info.ibd |
    | 17 | ./mysql/slave_worker_info.ibd |
    | 18 | ./mysql/gtid_executed.ibd |
    | 19 | ./mysql/server_cost.ibd |
    | 20 | ./mysql/engine_cost.ibd |
    | 21 | ./sys/sys_config.ibd |
    | 23 | ./test/t1.ibd |
    | 26 | /home/user/test/test/t2.ibd |
    + --------- + --------------------------------------- +

该查询检索FILE_IDFILE_NAME用于InnoDB 临时表空间。临时表空间文件名以前缀为ibtmp

MySQL的> SELECT FILE_ID, FILE_NAME FROM INFORMATION_SCHEMA.FILES
       WHERE FILE_NAME LIKE '%ibtmp%';
+ --------- + ----------- +
| FILE_ID | FILE_NAME |
+ --------- + ----------- +
| 22 | ./ibtmp1 |
+ --------- + ----------- +

同样,InnoDB撤消表空间文件名称的前缀为undo下面的查询返回的FILE_IDFILE_NAMEInnoDB撤消表空间,如果单独的还原表进行配置。

MySQL的> SELECT FILE_ID, FILE_NAME FROM INFORMATION_SCHEMA.FILES
       WHERE FILE_NAME LIKE '%undo%';

14.16 InnoDB与MySQL性能模式的集成

本节简要介绍 InnoDB与Performance Schema的集成。有关全面的性能模式文档,请参见 第25章MySQL性能模式

您可以InnoDB 使用MySQL 性能模式功能分析某些内部操作 此类调整主要针对评估优化策略以克服性能瓶颈的专家用户。DBA还可以将此功能用于容量规划,以查看其典型工作负载是否遇到CPU,RAM和磁盘存储的特定组合的任何性能瓶颈; 如果是的话,可以通过增加系统某些部分的容量来判断性能是否可以得到改善。

要使用此功能来检查InnoDB 性能:

  • 您一定熟悉如何使用 性能模式功能例如,您应该知道如何启用仪器和消费者,以及如何查询 performance_schema表以检索数据。有关介绍性概述,请参见 第25.1节“性能架构快速入门”

  • 您应该熟悉可用的性能模式工具InnoDB要查看 InnoDB相关的乐器,可以在setup_instruments表格中查询 包含' innodb'的乐器名称

    MySQL的> SELECT * FROM setup_instruments WHERE NAME LIKE '%innodb%';
    + ------------------------------------------------- ------ + --------- + ------- +
    | NAME | ENABLED | TIMED |
    + ------------------------------------------------- ------ + --------- + ------- +
    | wait / synch / mutex / innodb / commit_cond_mutex | NO | NO |
    | wait / synch / mutex / innodb / innobase_share_mutex | NO | NO |
    | wait / synch / mutex / innodb / autoinc_mutex | NO | NO |
    | wait / synch / mutex / innodb / buf_pool_mutex | NO | NO |
    | wait / synch / mutex / innodb / buf_pool_zip_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / cache_last_read_mutex | NO | NO |
    | wait / synch / mutex / innodb / dict_foreign_err_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / dict_sys_mutex | NO | NO |
    | wait / synch / mutex / innodb / recalc_pool_mutex | NO | NO |
    | wait / synch / mutex / innodb / file_format_max_mutex | NO | NO |
    ...
    | wait / io / file / innodb / innodb_data_file | 是| 是|
    | wait / io / file / innodb / innodb_log_file | 是| 是|
    | wait / io / file / innodb / innodb_temp_file | 是| 是|
    | stage / innodb / alter table(end)| 是| 是|
    | stage / innodb / alter table(flush)| 是| 是|
    | stage / innodb / alter table(insert)| 是| 是|
    | stage / innodb / alter table(日志应用索引)| 是| 是|
    | stage / innodb / alter table(日志应用表)| 是| 是|
    | stage / innodb / alter table(合并排序)| 是| 是|
    | stage / innodb / alter table(读取PK和内部排序)| 是| 是|
    | stage / innodb /缓冲池加载| 是| 是|
    | 内存/ innodb / buf_buf_pool | NO | NO |
    | 内存/ innodb / dict_stats_bg_recalc_pool_t | NO | NO |
    | 内存/ innodb / dict_stats_index_map_t | NO | NO |
    | 内存/ innodb / dict_stats_n_diff_on_level | NO | NO |
    | 内存/ innodb / other | NO | NO |
    | 内存/ innodb / row_log_buf | NO | NO |
    | 内存/ innodb / row_merge_sort | NO | NO |
    | 内存/ innodb / std | NO | NO |
    | 内存/ innodb / sync_debug_latches | NO | NO |
    | 内存/ innodb / trx_sys_t :: rw_trx_ids | NO | NO |
    ...
    + ------------------------------------------------- ------ + --------- + ------- +
    一套155行(0.00秒)
    

    有关检测InnoDB对象的其他信息 ,可以查询性能模式 实例表,其中提供了有关检测对象的附加信息。与相关的实例表 InnoDB包括:

    注意

    与此InnoDB 缓冲池相关的互斥锁和RW锁不包括在此范围内; 这同样适用于SHOW ENGINE INNODB MUTEX命令的输出

    例如,要查看InnoDB执行文件I / O检测时由性能模式看到的有关检测文件对象的信息 ,可以发出以下查询:

    MySQL的> SELECT * FROM file_instances WHERE EVENT_NAME LIKE '%innodb%'\G
    *************************** 1. row ******************** *******
     FILE_NAME:/path/to/mysql-5.7/data/ibdata1
    EVENT_NAME:wait / io / file / innodb / innodb_data_file
    OPEN_COUNT:3
    *************************** 2. row ******************** *******
     FILE_NAME:/path/to/mysql-5.7/data/ib_logfile0
    EVENT_NAME:wait / io / file / innodb / innodb_log_file
    OPEN_COUNT:2
    *************************** 3. row ******************** *******
     FILE_NAME:/path/to/mysql-5.7/data/ib_logfile1
    EVENT_NAME:wait / io / file / innodb / innodb_log_file
    OPEN_COUNT:2
    *************************** 4. row ******************** *******
     FILE_NAME:/path/to/mysql-5.7/data/mysql/engine_cost.ibd
    EVENT_NAME:wait / io / file / innodb / innodb_data_file
    OPEN_COUNT:3
    ...
    
  • 您应该熟悉 performance_schema存储InnoDB事件数据的InnoDB相关事件相关的表格 包括:

    如果您只对InnoDB相关对象感兴趣,请在查询这些表时使用该子句WHERE EVENT_NAME LIKE '%innodb%'WHERE NAME LIKE '%innodb%'(根据需要)。

14.16.1使用性能模式监控InnoDB表的ALTER TABLE进度

您可以使用性能模式监控表的 ALTER TABLE 进度InnoDB

有七个舞台事件代表不同的阶段 ALTER TABLE每个阶段事件都会在整个不同阶段进展时报告总体运行情况WORK_COMPLETEDWORK_ESTIMATED总体 ALTER TABLE运行情况。 WORK_ESTIMATED是用一个公式计算的,该公式考虑了所有ALTER TABLE执行的工作 ,并可能在ALTER TABLE 处理过程中进行修改WORK_COMPLETEDWORK_ESTIMATED值全部所执行的工作的的抽象表示 ALTER TABLE

按照发生的顺序,ALTER TABLE 舞台事件包括:

  • stage/innodb/alter table (read PK and internal sort):这个阶段ALTER TABLE在阅读主键阶段处于活动 状态。它以开始 WORK_COMPLETED=0WORK_ESTIMATED设置为主键中的估计页数。阶段完成后, WORK_ESTIMATED更新为主键中的实际页数。

  • stage/innodb/alter table (merge sort):对于ALTER TABLE操作添加的每个索引重复此阶段

  • stage/innodb/alter table (insert):对于ALTER TABLE操作添加的每个索引重复此阶段

  • stage/innodb/alter table (log apply index):该阶段包括ALTER TABLE运行时生成的DML日志的应用程序

  • stage/innodb/alter table (flush):在此阶段开始之前WORK_ESTIMATED,基于冲刷清单的长度更新为更准确的估计值。

  • stage/innodb/alter table (log apply table):这个阶段包括ALTER TABLE运行时生成的并发DML日志的应用程序这个阶段的持续时间取决于表格变化的程度。如果没有并发DML在桌面上运行,这个阶段是即时的。

  • stage/innodb/alter table (end):包括在刷新阶段后出现的任何剩余工作,例如重新应用ALTER TABLE在运行时在表上执行的DML

注意

InnoDB ALTER TABLE 舞台事件目前不占空间索引的增加。

使用性能模式的ALTER TABLE监控示例

以下示例演示如何启用 stage/innodb/alter table%舞台事件工具和相关的使用者表来监视 ALTER TABLE进度。有关Performance Schema阶段事件工具和相关使用者的信息,请参见 第25.11.5节“性能模式阶段事件表”

  1. 启用stage/innodb/alter%仪器:

    MySQL的> UPDATE setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE 'stage/innodb/alter%';
    查询OK,7行受影响(0.00秒)
    匹配行数:7更改:7警告:0
    
  2. 启用舞台活动消费表,其中包括 events_stages_currentevents_stages_history,和 events_stages_history_long

    MySQL的> UPDATE setup_consumers SET ENABLED = 'YES' WHERE NAME LIKE '%stages%';
    查询OK,3行受影响(0.00秒)
    匹配行数:3更改:3警告:0
    
  3. 运行一个ALTER TABLE操作。在这个例子中,一个middle_name列被添加到员工样本数据库的employees表中。

    MySQL的> ALTER TABLE employees.employees ADD COLUMN middle_name varchar(14) AFTER first_name;
    查询OK,0行受影响(9.27秒)
    记录:0重复:0警告:0
    
  4. ALTER TABLE通过查询性能模式events_stages_current 检查操作 的进度所显示的舞台事件取决于ALTER TABLE当前正在进行的阶段而有所不同 WORK_COMPLETED列显示已完成的工作。WORK_ESTIMATED列提供了剩余工作的估计。

    MySQL的> SELECT EVENT_NAME, WORK_COMPLETED, WORK_ESTIMATED FROM events_stages_current;
    + ------------------------------------------------- ----- + ---------------- + ---------------- +
    | EVENT_NAME | WORK_COMPLETED | WORK_ESTIMATED |
    + ------------------------------------------------- ----- + ---------------- + ---------------- +
    | stage / innodb / alter table(读取PK和内部排序)| 280 | 1245 |
    + ------------------------------------------------- ----- + ---------------- + ---------------- +
    一排(0.01秒)
    

    events_stages_current如果ALTER TABLE操作已完成表格将返回一个空集在这种情况下,您可以检查events_stages_history 表以查看已完成操作的事件数据。例如:

    MySQL的> SELECT EVENT_NAME, WORK_COMPLETED, WORK_ESTIMATED FROM events_stages_history;
    + ------------------------------------------------- ----- + ---------------- + ---------------- +
    | EVENT_NAME | WORK_COMPLETED | WORK_ESTIMATED |
    + ------------------------------------------------- ----- + ---------------- + ---------------- +
    | stage / innodb / alter table(读取PK和内部排序)| 886 | 1213 |
    | stage / innodb / alter table(flush)| 1213 | 1213 |
    | stage / innodb / alter table(日志应用表)| 1597 | 1597 |
    | stage / innodb / alter table(end)| 1597 | 1597 |
    | stage / innodb / alter table(日志应用表)| 1981 | 1981 |
    + ------------------------------------------------- ----- + ---------------- + ---------------- +
    5行(0.00秒)
    

    如上所示,该WORK_ESTIMATED值在ALTER TABLE处理过程中进行了修改初始阶段完成后的估计工作是1213年。ALTER TABLE处理完成后,WORK_ESTIMATED设定为实际值,即1981年。

14.16.2使用性能模式监控InnoDB互斥量等待

互斥锁是代码中使用的同步机制,用于强制在给定时间只有一个线程可以访问公共资源。当服务器中执行的两个或更多线程需要访问相同的资源时,这些线程相互竞争。获得对互斥锁的第一个线程会导致其他线程等待,直到释放锁。

对于已InnoDB插装的互斥锁,可以使用性能架构来监视互斥锁等待 例如,在性能模式表中收集的等待事件数据可以帮助识别等待时间最长或总等待时间最长的互斥量。

以下示例演示如何启用 InnoDB互斥等待工具,如何启用关联的使用者以及如何查询等待事件数据。

  1. 要查看可用的InnoDB互斥等待工具,请查询性能模式 setup_instruments表,如下所示。所有的InnoDB互斥等待仪器默认是禁用的。

    MySQL的> SELECT * FROM performance_schema.setup_instruments
           WHERE NAME LIKE '%wait/synch/mutex/innodb%';
    + ------------------------------------------------- ------ + --------- + ------- +
    | NAME | ENABLED | TIMED |
    + ------------------------------------------------- ------ + --------- + ------- +
    | wait / synch / mutex / innodb / commit_cond_mutex | NO | NO |
    | wait / synch / mutex / innodb / innobase_share_mutex | NO | NO |
    | wait / synch / mutex / innodb / autoinc_mutex | NO | NO |
    | wait / synch / mutex / innodb / buf_pool_mutex | NO | NO |
    | wait / synch / mutex / innodb / buf_pool_zip_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / cache_last_read_mutex | NO | NO |
    | wait / synch / mutex / innodb / dict_foreign_err_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / dict_sys_mutex | NO | NO |
    | wait / synch / mutex / innodb / recalc_pool_mutex | NO | NO |
    | wait / synch / mutex / innodb / file_format_max_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / fil_system_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / flush_list_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / fts_bg_threads_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / fts_delete_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / fts_optimize_mutex | NO | NO |
    | wait / synch / mutex / innodb / fts_doc_id_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / log_flush_order_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / hash_table_mutex | NO | NO |
    | wait / synch / mutex / innodb / ibuf_bitmap_mutex | NO | NO |
    | wait / synch / mutex / innodb / ibuf_mutex | NO | NO |
    | wait / synch / mutex / innodb / ibuf_pessimistic_insert_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / log_sys_mutex | NO | NO |
    | wait / synch / mutex / innodb / page_zip_stat_per_index_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / purge_sys_pq_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / recv_sys_mutex | NO | NO |
    | wait / synch / mutex / innodb / recv_writer_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / redo_rseg_mutex | NO | NO |
    | wait / synch / mutex / innodb / noredo_rseg_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / rw_lock_list_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / rw_lock_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / srv_dict_tmpfile_mutex | NO | NO |
    | wait / synch / mutex / innodb / srv_innodb_monitor_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / srv_misc_tmpfile_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / srv_monitor_file_mutex | NO | NO |
    | wait / synch / mutex / innodb / buf_dblwr_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / trx_undo_mutex | NO | NO |
    | wait / synch / mutex / innodb / trx_pool_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / trx_pool_manager_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / srv_sys_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / lock_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / lock_wait_mutex | NO | NO |
    | wait / synch / mutex / innodb / trx_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / srv_threads_mutex | NO | NO |
    | wait / synch / mutex / innodb / rtr_active_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / rtr_match_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / rtr_path_mutex | NO | NO |
    | 等待/同步/互斥/ innodb / rtr_ssn_mutex | NO | NO |
    | wait / synch / mutex / innodb / trx_sys_mutex | NO | NO |
    | wait / synch / mutex / innodb / zip_pad_mutex | NO | NO |
    + ------------------------------------------------- ------ + --------- + ------- +
    一组49行(0.02秒)
    
  2. 一些InnoDB互斥体实例在服务器启动时创建,并且只有在服务器启动时也启用相关仪器时才会进行插装。为确保所有InnoDB互斥实例都被检测和启用,请将以下performance-schema-instrument规则添加 到您的MySQL配置文件中:

    性能架构仪器= '等待/同步/互斥/ innodb的/%= ON'
    

    如果您不需要所有InnoDB互斥锁的等待事件数据 ,则可以通过向performance-schema-instrumentMySQL配置文件添加其他规则来禁用特定仪器 例如,要禁用 InnoDB与全文搜索相关的互斥锁等待事件工具,请添加以下规则:

    性能架构仪器= '等待/同步/互斥/ innodb的/ FTS(%)= OFF'
    
    注意

    具有较长前缀的规则(例如 wait/synch/mutex/innodb/fts%优先于具有较短前缀的规则,例如) wait/synch/mutex/innodb/%

    performance-schema-instrument规则添加 到配置文件后,重新启动服务器。InnoDB除与全文搜索相关的所有互斥锁以外,所有 互斥锁都已启用。要验证,请查询 setup_instruments表格。ENABLEDTIMED 列应设置YES为您启用的工具。

    MySQL的> SELECT * FROM performance_schema.setup_instruments
            WHERE NAME LIKE '%wait/synch/mutex/innodb%';
    + ------------------------------------------------- ------ + --------- + ------- +
    | NAME | ENABLED | TIMED |
    + ------------------------------------------------- ------ + --------- + ------- +
    | wait / synch / mutex / innodb / commit_cond_mutex | 是| 是|
    | wait / synch / mutex / innodb / innobase_share_mutex | 是| 是|
    | wait / synch / mutex / innodb / autoinc_mutex | 是| 是|
    ...
    | wait / synch / mutex / innodb / zip_pad_mutex | 是| 是|
    + ------------------------------------------------- ------ + --------- + ------- +
    设置49行(0.00秒)
    
  3. 通过更新setup_consumers表来启用等待事件使用者 等待事件使用者默认是禁用的。

    MySQL的> UPDATE performance_schema.setup_consumers SET enabled = 'YES'
           WHERE name like 'events_waits%';
    查询OK,3行受影响(0.00秒)
    匹配行数:3更改:3警告:0
    

    您可以通过查询setup_consumers来验证是否启用了等待事件使用者events_waits_currentevents_waits_historyevents_waits_history_long 消费者应该启用。

    MySQL的> SELECT * FROM performance_schema.setup_consumers;
    + ---------------------------------- + --------- +
    | NAME | ENABLED |
    + ---------------------------------- + --------- +
    | events_stages_current | NO |
    | events_stages_history | NO |
    | events_stages_history_long | NO |
    | events_statements_current | 是|
    | events_statements_history | 是|
    | events_statements_history_long | NO |
    | events_transactions_current | 是|
    | events_transactions_history | 是|
    | events_transactions_history_long | NO |
    | events_waits_current | 是|
    | events_waits_history | 是|
    | events_waits_history_long | 是|
    | global_instrumentation | 是|
    | thread_instrumentation | 是|
    | statement_digest | 是|
    + ---------------------------------- + --------- +
    15行(0.00秒)
    
  4. 一旦启用仪器和消费者,运行您要监控的工作负荷。在这个例子中, mysqlslap负载仿真客户端用于模拟工作负载。

    外壳> ./mysqlslap --auto-generate-sql --concurrency=100 --iterations=10
           --number-of-queries=1000 --number-char-cols=6 --number-int-cols=6;
    
  5. 查询等待事件数据。在这个例子中,等待事件数据从查询 events_waits_summary_global_by_event_name ,其聚合中找到的数据表 events_waits_currentevents_waits_historyevents_waits_history_long表。数据通过事件名称(EVENT_NAME)进行汇总,事件名称是生成事件的工具的名称。汇总数据包括:

    • COUNT_STAR

      汇总的等待事件的数量。

    • SUM_TIMER_WAIT

      汇总的定时等待事件的总等待时间。

    • MIN_TIMER_WAIT

      汇总的定时等待事件的最短等待时间。

    • AVG_TIMER_WAIT

      汇总的定时等待事件的平均等待时间。

    • MAX_TIMER_WAIT

      汇总的定时等待事件的最长等待时间。

    以下查询返回仪器名称(EVENT_NAME),等待事件数量(COUNT_STAR)以及该仪器事件()的总等待时间SUM_TIMER_WAIT因为默认情况下,等待时间以皮秒为单位(十亿分之一秒),所以等待时间除以1000000000以显示以毫秒为单位的等待时间。数据按降序排列,按汇总等待事件(COUNT_STAR的数量表示您可以ORDER BY通过总等待时间调整 子句以排序数据。

    MySQL的> SELECT EVENT_NAME, COUNT_STAR, SUM_TIMER_WAIT/1000000000 SUM_TIMER_WAIT_MS
           FROM performance_schema.events_waits_summary_global_by_event_name
           WHERE SUM_TIMER_WAIT > 0 AND EVENT_NAME LIKE 'wait/synch/mutex/innodb/%'
           ORDER BY COUNT_STAR DESC;
    + ------------------------------------------------- -  + ------------ + ------------------- +
    | EVENT_NAME | COUNT_STAR | SUM_TIMER_WAIT_MS |
    + ------------------------------------------------- -  + ------------ + ------------------- +
    | 等待/同步/互斥/ innodb / os_mutex | 78831 | 10.3283 |
    | 等待/同步/互斥/ innodb / log_sys_mutex | 41488 | 6510.3233 |
    | wait / synch / mutex / innodb / trx_sys_mutex | 29770 | 1107.9687 |
    | 等待/同步/互斥/ innodb / lock_mutex | 24212 | 104.0724 |
    | wait / synch / mutex / innodb / trx_mutex | 22756 | 1.9421 |
    | 等待/同步/互斥/ innodb / rseg_mutex | 20333 | 3.6220 |
    | 等待/同步/互斥/ innodb / dict_sys_mutex | 13422 | 2.2284 |
    | 等待/同步/互斥/ innodb / mutex_list_mutex | 12694 | 344.1164 |
    | 等待/同步/互斥/ innodb / fil_system_mutex | 9208 | 0.9542 |
    | 等待/同步/互斥/ innodb / rw_lock_list_mutex | 8304 | 0.1794 |
    | 等待/同步/互斥/ innodb / trx_undo_mutex | 6190 | 0.6801 |
    | wait / synch / mutex / innodb / buf_pool_mutex | 2869 | 29.4623 |
    | wait / synch / mutex / innodb / innobase_share_mutex | 2005 | 0.1349 |
    | 等待/同步/互斥/ innodb / flush_list_mutex | 1274 | 0.1300 |
    | wait / synch / mutex / innodb / file_format_max_mutex | 1016 | 0.0469 |
    | wait / synch / mutex / innodb / purge_sys_bh_mutex | 1004 | 0.0326 |
    | wait / synch / mutex / innodb / buf_dblwr_mutex | 640 | 0.0437 |
    | 等待/同步/互斥/ innodb / log_flush_order_mutex | 437 | 0.0510 |
    | 等待/同步/互斥/ innodb / recv_sys_mutex | 394 | 0.0202 |
    | 等待/同步/互斥/ innodb / srv_sys_mutex | 169 | 0.5259 |
    | 等待/同步/互斥/ innodb / lock_wait_mutex | 154 | 0.1172 |
    | wait / synch / mutex / innodb / ibuf_mutex | 9 | 0.0027 |
    | wait / synch / mutex / innodb / srv_innodb_monitor_mutex | 2 | 0.0009 |
    | 等待/同步/互斥/ innodb / ut_list_mutex | 1 | 0.0001 |
    | wait / synch / mutex / innodb / recv_writer_mutex | 1 | 0.0005 |
    + ------------------------------------------------- -  + ------------ + ------------------- +
    25行(0.01秒)
    
    注意

    上述结果集包括启动过程中生成的等待事件数据。要排除此数据,可以events_waits_summary_global_by_event_name 在启动之后和运行工作负载之前立即截断 表。但是,截断操作本身可能会产生可忽略的数量等待事件数据。

    MySQL的> TRUNCATE performance_schema.events_waits_summary_global_by_event_name;
    

14.17 InnoDB监视器

InnoDB监视器提供有关 InnoDB内部状态的信息。这些信息对性能调整很有用。

14.17.1 InnoDB监视器类型

有两种类型的InnoDB显示器:

  • 标准InnoDB监视器显示以下类型的信息:

    • 由主后台线程完成的工作

    • 信号量等待

    • 有关最近的外键和死锁错误的数据

    • Lock等待交易

    • 表和活动事务持有的记录锁

    • 等待I / O操作和相关统计

    • 插入缓冲区和自适应散列索引统计

    • 重做日志数据

    • 缓冲池统计信息

    • 行操作数据

  • InnoDB锁监控打印附加锁信息作为标准的一部分 InnoDB监视器输出。

14.17.2启用InnoDB监视器

InnoDB监视器启用周期性输出时,InnoDB输出写入 mysqld服务器标准错误输出(stderr)。InnoDB将诊断输出发送给内存缓冲区stderr而不是 stdout固定大小的内存以避免潜在的缓冲区溢出。

在Windows上,stderr除非另行配置,否则将指向默认日志文件。如果要将输出定向到控制台窗口而不是错误日志,请使用--console选项在控制台窗口中的命令提示符下启动服务器 有关更多信息,请参见第5.4.2.1节“Windows上的错误日志记录”

在Unix和类Unix系统上,stderr除非另行配置,否则通常指向终端。有关更多信息,请参见第5.4.2.2节“在Unix和类Unix系统上的错误日志记录”

启用后,InnoDB每15秒监控一次打印数据。这些数据在性能调优中非常有用。作为副作用,SHOW ENGINE INNODB STATUS每15秒将输出 写入MySQL数据目录中的状态文件。该文件的名称是 服务器进程ID 在哪里当服务器正常关闭时删除文件。如果发生异常关闭,则可能存在这些状态文件的实例,必须手动删除。在删除文件之前,请检查它们是否包含有关异常关闭原因的有用信息。一个 文件只有在创建 innodb_status.pidpidInnoDBinnodb_status.pidinnodb-status-file配置选项已启用。它默认是禁用的。

InnoDB监视器只应在您确实想查看监视器信息时启用,因为输出生成会导致性能下降。另外,如果监视器输出指向错误日志,那么如果您以后忘记禁用监视器,日志可能会变得非常大。

注意

为了帮助排除故障,在特定条件下InnoDB 暂时启用标准InnoDB监视器输出。有关更多信息,请参见 第14.21节“InnoDB故障排除”

InnoDB监视器输出以包含时间戳和监视器名称的标题开头。例如:

=====================================
2014-10-16 18:37:29 0x7fc2a95c1700 INNODB MONITOR OUTPUT
=====================================

标准InnoDBMonitor(INNODB MONITOR OUTPUT的标题也用于锁定监视器,因为后者会产生相同的输出并增加额外的锁定信息。

innodb_status_outputinnodb_status_output_locks系统变量用于启用标准的 InnoDB监控和InnoDB 锁定监控。

PROCESS权限是启用或禁用InnoDB监视器所必需的

启用标准InnoDB监视器

InnoDB通过将innodb_status_output系统变量设置为, 启用标准监视器ON

SET GLOBAL innodb_status_output = ON;

要禁用标准InnoDB监视器,请设置 innodb_status_outputOFF

当你关闭服务器时, innodb_status_output变量被设置为默认OFF值。

按需获取标准InnoDB Monitor输出

作为启用标准InnoDBMonitor以进行周期性输出的替代方法 ,您可以InnoDB使用SHOW ENGINE INNODB STATUSSQL语句按需获取标准Monitor输出,该语句将输出提取到客户端程序。如果您使用的是mysql 交互式客户端,那么如果将常用的分号语句终结符替换为\G

MySQL的> SHOW ENGINE INNODB STATUS\G

SHOW ENGINE INNODB STATUSInnoDB 如果InnoDB启用锁定监视器,输出还包括锁定监视器数据

启用InnoDB锁定监视器

InnoDB使用InnoDB标准监视器输出打印锁定监视器数据 无论是 InnoDB标准监视器和 InnoDB锁显示器必须能够具有 InnoDB锁定监控数据定期打印。

要启用InnoDB锁定监视器,请将innodb_status_output_locks系统变量设置 ON无论是 InnoDB标准的监控和 InnoDB锁定显示器必须能够有 InnoDB定期打印锁监视器数据:

SET GLOBAL innodb_status_output = ON;
SET GLOBAL innodb_status_output_locks = ON;

要禁用InnoDB锁定监视器,请设置 innodb_status_output_locksOFF设置 innodb_status_outputOFF也禁用 InnoDB标准监视器。

关闭服务器时, 变量innodb_status_outputinnodb_status_output_locks变量将设置为默认OFF值。

注意

要启用InnoDB锁定监视器 SHOW ENGINE INNODB STATUS输出,只需启用 innodb_status_output_locks

14.17.3 InnoDB标准监视器和锁定监视器输出

锁定监视器与标准监视器相同,只是它包含附加的锁定信息。启用任一监视器以进行周期性输出会打开相同的输出流,但如果锁定监视器已启用,则该流将包含额外信息。例如,如果启用标准监视器和锁定监视器,则会打开单个输出流。该流包括额外的锁定信息,直到您禁用锁定监视器。

使用该SHOW ENGINE INNODB STATUS语句生成时,标准监视器输出限制为1MB 此限制不适用于写入tserver标准错误输出(stderr)的输出

示例标准监视器输出:

MySQL的> SHOW ENGINE INNODB STATUS\G
*************************** 1. row ******************** *******
  类型:InnoDB
  名称:
状态:
=====================================
2014-10-16 18:37:29 0x7fc2a95c1700 INNODB MONITOR OUTPUT
=====================================
从最近20秒计算的每秒平均值
-----------------
背景线程
-----------------
srv_master_thread循环:38 srv_active,0 srv_shutdown,252 srv_idle
srv_master_thread日志刷新并写入:290
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO:预留计数119
OS WAIT ARRAY INFO:信号计数103
互斥量等待0,循环0,OS等待0
RW共享旋转38,第76轮,OS等待38
RW-excl转2,轮9383715,OS等待3
RW-sx旋转0,轮0,OS等待0
每轮等待旋转次数:0.00互斥量,2.00 RW共享,4691857.50 RW-excl,
0.00 RW-sx
------------------------
最新的外键错误
------------------------
2014-10-16 18:35:18 0x7fc2a95c1700交易:
TRANSACTION 1814,ACTIVE 0秒插入
mysql表在使用1,锁定1
4个锁结构,堆大小1136,3个行锁,撤销日志条目3
MySQL线程ID 2,操作系统线程句柄140474041767680,查询ID 74本地主机
根更新
插入到子值中
    (NULL,1)
    ,(NULL,2)
    ,(NULL,3)
    ,(NULL,4)
    ,(NULL,5)
    ,(NULL,6)
表“mysql`.`child`的外键约束失败:
  CONSTRAINT`child_ibfk_1` FOREIGN KEY(`parent_id`)REFERENCES`parent`
  (`id`)ON DELETE CASCADE ON UPDATE CASCADE
尝试在索引par_ind元组中添加子表:
DATA TUPLE:2个字段;
 0:len 4; 十六进制80000003; asc ;;
 1:len 4; 十六进制80000003; asc ;;

但在父表`mysql`.`parent`中,在索引PRIMARY中,
我们可以找到最接近的匹配记录:
物理记录:n_fields 3; 紧凑格式; 信息位0
 0:len 4; 十六进制80000004; asc ;;
 1:len 6; 十六进制00000000070a; asc ;;
 2:len 7; 十六进制aa0000011d0134; asc 4 ;;

------------------------
最新检测到的死锁
------------------------
2014-10-16 18:36:30 0x7fc2a95c1700
***(1)交易:
TRANSACTION 1824,ACTIVE 9秒开始索引读取
mysql表在使用1,锁定1
LOCK WAIT 2锁结构,堆大小1136,1行锁(s)
MySQL线程ID 3,操作系统线程句柄140474041501440,查询ID 80本地主机
根更新
删除从哪里我= 1
***(1)等待这个锁定被允许:
RECORD LOCKS空间ID 35页面号3 n位72索引表GEN_CLUST_INDEX
`mysql`.`t` trx id 1824 lock_mode X等待
记录锁定,堆号2物理记录:n_fields 4; 紧凑格式; 信息
位0
 0:len 6; 十六进制000000000200; asc ;;
 1:len 6; 十六进制00000000071f; asc ;;
 2:len 7; 十六进制b80000012b0110; asc + ;;
 3:len 4; 六角形80000001; asc ;;

***(2)交易:
TRANSACTION 1825,ACTIVE 29秒开始索引读取
mysql表在使用1,锁定1
4个锁结构,堆大小1136,3个行锁(s)
MySQL线程ID 2,OS线程句柄140474041767680,查询ID 81本地主机
根更新
删除从哪里我= 1
***(2)锁定(S):
RECORD LOCKS空间ID 35页面号3 n位72索引表GEN_CLUST_INDEX
`mysql`.`t` trx id 1825锁定模式S
记录锁定,堆号1物理记录:n_fields 1; 紧凑格式; 信息
位0
 0:len 8; 十六进制73757072656d756d; asc supremum ;;

记录锁定,堆号2物理记录:n_fields 4; 紧凑格式; 信息位0
 0:len 6; 十六进制000000000200; asc ;;
 1:len 6; 十六进制00000000071f; asc ;;
 2:len 7; 十六进制b80000012b0110; asc + ;;
 3:len 4; 六角形80000001; asc ;;

***(2)等待此锁定:
RECORD LOCKS空间ID 35页面号3 n位72索引表GEN_CLUST_INDEX
`mysql`.`t` trx id 1825 lock_mode X等待
记录锁定,堆号2物理记录:n_fields 4; 紧凑格式; 信息
位0
 0:len 6; 十六进制000000000200; asc ;;
 1:len 6; 十六进制00000000071f; asc ;;
 2:len 7; 十六进制b80000012b0110; asc + ;;
 3:len 4; 六角形80000001; asc ;;

***我们回卷交易(1)
------------
交易
------------
Trx id counter 1950
清除trx的n:o <1933 undo n:o <0状态:正在运行但空闲
历史列表长度23
每个会话的交易清单:
--- TRANSACTION 421949033065200,未开始
0锁结构,堆大小1136,0行锁(s)
--- TRANSACTION 421949033064280,未开始
0锁结构,堆大小1136,0行锁(s)
--- TRANSACTION 1949,活动0秒插入
mysql表在使用1,锁定1
8个锁结构,堆大小1136,1850行锁,撤消日志条目17415
MySQL线程ID 4,操作系统线程句柄140474041235200,查询ID 176本地主机
根更新
INSERT INTO`salaries` VALUES(55723,39746,'1997-02-25','1998-02-25'),
(55723,40758, '1998年2月25日', '1999-02-25'),(55723,44559 '1999-02-25', '2000年2月25日'),
(55723,44081, '2000年2月25日', '2001年2月24日'),(55723,44112, '2001年2月24日', '2001-08-16'),
(55724,46461, '1996年12月6日', '1997年12月6日'),(55724,48916, '1997年12月6日', '1998年12月6日'),
(55724,51269, '1998年12月6日', '1999年12月6日'),(55724,51932, '1999年12月6日', '2000年12月5日'),
(55724,52617, '2000年12月5日', '2001-12-05'),(55724,56658 '2001-12-05', '9999-01-01'),
(55725,40000, '1993年1月30日', '1994年1月30日'),(55725,41472, '1994年1月30日', '1995年1月30日'),
(55725,45293, '1995年1月30日', '1996-01-30'),(55725,473
--------
FILE I / O
--------
I / O线程0状态:等待已完成的aio请求(插入缓冲线程)
I / O线程1状态:等待已完成的aio请求(日志线程)
I / O线程2状态:等待已完成的aio请求(读取线程)
I / O线程3状态:等待已完成的aio请求(读取线程)
I / O线程4状态:等待已完成的aio请求(读取线程)
I / O线程5状态:等待已完成的aio请求(读取线程)
I / O线程6状态:等待已完成的aio请求(写入线程)
I / O线程7状态:等待已完成的aio请求(写入线程)
I / O线程8状态:等待已完成的aio请求(写入线程)
I / O线程9状态:等待已完成的aio请求(写入线程)
等待正常的aio读取:0 [0,0,0,0],aio写入:0 [0,0,0,0],
 ibuf aio读取:0,日志i / o's:0,同步i / o's:0
等待刷新(fsync)日志:0; 缓冲池:0
224个OS文件读取,5770个OS文件写入,803个OS fsyncs
0.00读取/秒,0平均字节/读取,264.84写入/秒,23.05 fsyncs /秒
-------------------------------------
INSERT BUFFER和ADAPTIVE HASH INDEX
-------------------------------------
Ibuf:大小1,空闲列表len 0,seg大小2,0合并
合并操作:
 插入0,删除标记0,删除0
丢弃的操作:
 插入0,删除标记0,删除0
哈希表大小4425293,节点堆有444个缓冲区(s)
68015.25散列搜索/ s,106259.24非散列搜索/ s
---
LOG
---
日志序号165913808
日志刷新到164814979
页面刷新到141544038
最后一个检查点在130503656
0等待日志刷新,0等待chkp写入
258日志I / O完成,6.65日志I / O /秒
----------------------
缓冲池和内存
----------------------
总大内存分配2198863872
分配了字典内存776332
缓冲池大小131072
空闲缓冲区124908
数据库页面5720
旧数据库页面2071
修改的数据页面910
等待读取0
等待写入:LRU 0,刷新列表0,单个页面0
年轻的4页,而不是年轻的0
0.10个年轻人/ s,0.00个非年轻人/ s
页面读取197,创建5523,写入5060
0.00读/秒,190.89创/秒,244.94写/秒
缓冲池命中率为1000/1000,年轻化率为0/1000
0/1000
提前读取的页数为0.00 / s,无需访问驱逐0.00 /秒,随机读取
前进0.00 /秒
LRU len:5720,unzip_LRU len:0
I / O sum [0]:cur [0],unzip sum [0]:cur [0]
----------------------
个人缓冲池信息
----------------------
--- BUFFER POOL 0
缓冲池大小65536
空闲缓冲区62412
数据库页面2899
旧的数据库页面1050
修改的数据库页面449
等待读取0
等待写入:LRU 0,刷新列表0,单个页面0
年轻的3页,而不是年轻的0
0.05个青少年/ s,0.00个非青少年/ s
页数为107,创建2792,编写为2586
0.00读/秒,92.65次/秒,122.89次/秒
缓冲池命中率1000/1000,年轻化率0/1000不为0/1000
提前读取的页数为0.00 /秒,无需访问驱逐0.00 /秒,随机预读
0.00 /秒
LRU len:2899,unzip_LRU len:0
I / O sum [0]:cur [0],unzip sum [0]:cur [0]
---缓冲池1
缓冲池大小65536
空闲缓冲区62496
数据库页面2821
旧数据库页面1021
修改的数据库页面461
等待读取0
等待写入:LRU 0,刷新列表0,单个页面0
年轻的页面1,而不是年轻的0
0.05个青少年/ s,0.00个非青少年/ s
页数为90,创建2731,写入2474
0.00读/秒,98.25创/秒,122.04 /秒
缓冲池命中率1000/1000,年轻化率0/1000不为0/1000
提前读取的页数为0.00 /秒,无需访问驱逐0.00 /秒,随机预读
0.00 /秒
LRU len:2821,unzip_LRU len:0
I / O sum [0]:cur [0],unzip sum [0]:cur [0]
--------------
行操作
--------------
在InnoDB中查询0个,在队列中查询0个
0读取InnoDB内部的视图
进程ID = 35909,主线程ID = 140471692396288,状态:正在休眠
插入的行数1526363,更新了0,删除了3,读取了11
52671.72插入/秒,0.00更新/秒,0.00删除/秒,0.00读/秒
----------------------------
INNODB MONITOR OUTPUT结束
============================

标准监视器输出部分

有关标准监视器报告的每个度量标准的说明,请参阅Oracle企业管理器中度量标准”一章, 了解MySQL数据库用户指南

  • Status

    本部分显示时间戳,监视器名称以及每秒平均值所基于的秒数。秒数是当前时间与上次InnoDB打印监视器输出之间的时间间隔

  • BACKGROUND THREAD

    这些srv_master_thread行显示了主后台线程完成的工作。

  • SEMAPHORES

    本部分报告线程等待信号量以及线程需要旋转或等待互斥锁或rw锁信号量的次数的统计信息。大量等待信号量的线程可能是磁盘I / O或内部争用问题的结果InnoDB争用可能是由于查询的严重并行性或操作系统线程调度中的问题。设置 innodb_thread_concurrency 系统变量小于默认值可能有助于这种情况。Spin rounds per wait 行显示每个操作系统等待互斥锁的自旋锁回合数。

    互斥量度量由...报告 SHOW ENGINE INNODB MUTEX

  • LATEST FOREIGN KEY ERROR

    本节提供有关最新的外键约束错误的信息。如果没有发生此类错误,则不存在。内容包括失败的语句以及失败约束和引用表和引用表的信息。

  • LATEST DETECTED DEADLOCK

    本节提供有关最新死锁的信息。如果没有发生死锁,则不存在。内容显示涉及哪些事务,每个正试图执行的语句,他们拥有和需要的锁,以及InnoDB 决定回滚以打破僵局的事务本节中报告的锁定模式在 第14.5.1节“InnoDB锁定”中进行了说明

  • TRANSACTIONS

    如果此部分报告锁定等待,您的应用程序可能会发生锁定争用。输出还可以帮助追踪事务死锁的原因。

  • FILE I/O

    本节提供有关InnoDB用于执行各种类型I / O的线程的信息 其中前几个专用于一般 InnoDB处理。内容还显示待处理I / O操作的信息以及I / O性能的统计信息。

    这些线程的数量由innodb_read_io_threadsinnodb_write_io_threads 参数控制 请参见第14.14节“InnoDB启动选项和系统变量”

  • INSERT BUFFER AND ADAPTIVE HASH INDEX

    本部分显示 InnoDB插入缓冲区(也称为更改缓冲区)的状态和自适应散列索引。

    有关相关信息,请参见 第14.4.2节“更改缓冲区”第14.4.3节“自适应散列索引”

  • LOG

    本部分显示有关InnoDB日志的信息 内容包括当前日志序列号,日志已刷新到磁盘的距离以及InnoDB最后一次检查点的位置 (请参见 第14.12.3节“InnoDB检查点”。)该部分还显示有关待处理写入和写入性能统计信息。

  • BUFFER POOL AND MEMORY

    本节介绍读取和写入页面的统计数据。您可以根据这些数字计算您的查询当前正在执行的数据文件I / O操作的数量。

    有关缓冲池统计信息的说明,请参见 第14.6.3.9节“使用InnoDB标准监控器监控缓冲池”有关缓冲池操作的更多信息,请参见第14.6.3.1节“InnoDB缓冲池”

  • ROW OPERATIONS

    本部分显示主线程正在执行的操作,包括每种类型的行操作的数量和性能比率。

14.18 InnoDB备份和恢复

本节介绍与InnoDB 备份和恢复相关的主题

14.18.1 InnoDB备份

安全数据库管理的关键是定期进行备份。根据您的数据量,MySQL服务器数量和数据库工作负载,您可以单独或组合使用这些备份技术: 使用MySQL Enterprise Backup进行热备份 ; 通过在MySQL服务器关闭时复制文件进行冷备份 ; 使用mysqldump进行逻辑备份获取较小的数据量或记录模式对象的结构。热备份和冷备份是 物理备份,用于复制实际的数据文件,可以由mysqld服务器直接使用, 以加快恢复速度。

使用MySQL Enterprise Backup是备份InnoDB数据的推荐方法

注意

InnoDB 不支持使用第三方备份工具恢复的数据库。

热备份

作为MySQL企业备份组件的一部分,mysqlbackup命令可让您备份正在运行的MySQL实例(包括InnoDB表),同时最大限度地减少操作中断,同时生成数据库的一致快照。mysqlbackup复制 InnoDB表时,InnoDB可以继续读取和写入 表。MySQL企业备份还可以创建压缩备份文件,并备份表和数据库的子集。结合MySQL二进制日志,用户可以执行时间点恢复。MySQL企业备份是MySQL企业订阅的一部分。有关更多详细信息,请参见第29.2节“MySQL企业备份概述”

冷备份

如果您可以关闭MySQL服务器,则可以进行物理备份,该备份由用于InnoDB管理其表的所有文件组成 使用以下步骤:

  1. 执行MySQL服务器缓慢关闭,并确保它停止没有错误。

  2. 将所有InnoDB数据文件(ibdata文件和 .ibd文件)复制到安全的地方。

  3. 表格的所有.frm文件 复制InnoDB到安全的地方。

  4. 将所有InnoDB日志文件(ib_logfile文件)复制到安全的地方。

  5. 将您的my.cnf配置文件或文件复制到安全的地方。

逻辑备份使用mysqldump

除物理备份外,建议您定期使用mysqldump转储表来创建逻辑备份 二进制文件可能会被破坏,而你没有注意到它。转储表存储在人类可读的文本文件中,因此发现表损坏变得更加容易。而且,由于格式更简单,严重数据损坏的可能性更小。mysqldump 还有一个--single-transaction 选项,可以在不锁定其他客户端的情况下制作一致的快照。请参见第7.3.1节“建立备份策略”

复制适用于InnoDB表格,因此您可以使用MySQL复制功能在要求高可用性的数据库站点上保留数据库副本。第14.19节“InnoDB和MySQL复制”

14.18.2 InnoDB恢复

本节介绍InnoDB恢复。主题包括:

时间点恢复

要从InnoDB进行物理备份的时刻数据库恢复到现在,即使在进行备份之前,也必须启用启用了二进制日志记录的MySQL服务器。要在还原备份后实现时间点恢复,可以应用在进行备份后发生的二进制日志中的更改。请参见 第7.5节“使用二进制日志进行时间点恢复(增量)”

从数据损坏或磁盘故障中恢复

如果数据库损坏或发生磁盘故障,则必须使用备份执行恢复。在腐败的情况下,首先找到没有损坏的备份。恢复基本备份后,使用mysqlbinlogmysql二进制日志文件进行时间点恢复,以恢复备份后发生的更改。

在某些数据库损坏的情况下,转储,删除和重新创建一个或几个损坏的表就足够了。您可以使用该 CHECK TABLE语句来检查表是否损坏,尽管CHECK TABLE自然无法检测到任何可能的损坏类型。

在某些情况下,明显的数据库页面损坏实际上是由于操作系统损坏其自己的文件缓存,并且磁盘上的数据可能没有问题。最好先尝试重新启动计算机。这样做可能会消除似乎是数据库页面损坏的错误。如果由于InnoDB一致性问题,MySQL仍然无法启动,请参见 第14.21.2节“强制InnoDB恢复”以获取以恢复模式启动实例的步骤,这允许您转储数据。

InnoDB崩溃恢复

要从MySQL服务器崩溃中恢复,唯一的要求是重新启动MySQL服务器。InnoDB 自动检查日志并执行数据库前滚至当前。InnoDB自动回滚崩溃时出现的未提交事务。在恢复过程中,mysqld 显示类似如下的输出:

InnoDB:日志扫描通过检查点lsn 369163704
InnoDB:执行恢复:扫描到日志序列号374340608
InnoDB:执行恢复:扫描到日志序列号379583488
InnoDB:执行恢复:扫描到日志序列号384826368
InnoDB:执行恢复:扫描到日志序列号390069248
InnoDB:执行恢复:扫描至记录序列号395312128
InnoDB:执行恢复:扫描到日志序列号400555008
InnoDB:执行恢复:扫描到日志序列号405797888
InnoDB:执行恢复:扫描到日志序列号411040768
InnoDB:执行恢复:扫描至记录序列号414724794
InnoDB:数据库没有正常关闭!
InnoDB:启动崩溃恢复。
InnoDB:1个必须回滚或清理的事务 
总共需要518425行操作才能撤消
InnoDB:Trx id counter是1792
InnoDB:开始对数据库应用一批日志记录...
InnoDB:百分比进展:0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 
InnoDB:应用批处理完成
...
InnoDB:从后台开始回滚未提交的事务
InnoDB:回滚trx,id为1511,518425行以撤消
...
InnoDB:等待清洗开始
InnoDB:5.7.18开始; 日志序列号414724794
...
./mysqld:准备好连接。

InnoDB 崩溃恢复 包括几个步骤:

  • 表空间发现

    表空间发现是InnoDB用于标识需要重做日志应用程序的表空间的过程 请参阅 崩溃恢复期间的表空间发现

  • 重做日志应用程序

    重做日志应用程序在初始化期间执行,然后接受任何连接。如果 在关闭或崩溃时将所有更改从缓冲池刷新表空间ibdata**.ibd文件),则会跳过重做日志应用程序。InnoDB如果重做日志文件在启动时丢失,也会跳过重做日志应用程序。

    不建议删除重做日志以加速恢复,即使可以接受某些数据丢失。只有在干净关闭后才能考虑删除重做日志,并将其 innodb_fast_shutdown设置为 01

    有关InnoDB用于识别需要重做日志应用程序的表空间的过程的信息 ,请参阅 崩溃恢复过程中的表空间发现

  • 回滚未完成的 交易

    不完整的事务是在崩溃或快速关闭时处于活动状态的任何事务 根据服务器负载,回滚未完成事务所花费的时间可能是事务处于活动状态之前的活动时间的三到四倍。

    您无法取消正在回滚的交易。在极端情况下,回滚事务预计需要很长时间时,InnoDBinnodb_force_recovery 设置3或更高开始可能会更快请参见 第14.21.2节“强制InnoDB恢复”

  • 更改缓冲区 合并

    因为将索引页读入缓冲池 ,所以将更改缓冲区(系统表空间的一部分)中的更改应用于 辅助索引的叶页。

  • 清除

    删除对活动事务不再可见的删除标记的记录。

重做日志应用程序后面的步骤不取决于重做日志(除了记录写入操作之外),并且与正常处理并行执行。其中,只有回滚未完成的交易对于崩溃恢复是特别的。插入缓冲区合并和清除在正常处理期间执行。

重做日志应用程序后,InnoDB尽可能早地尝试接受连接,以减少停机时间。作为崩溃恢复的一部分,InnoDB回滚XA PREPARE在服务器崩溃时未提交或处于状态的事务回滚由后台线程执行,与新连接的事务并行执行。在回滚操作完成之前,新连接可能会遇到与已恢复事务的锁定冲突。

在大多数情况下,即使MySQL服务器在繁重的活动中意外中止,恢复过程也会自动进行,并且不需要DBA的任何操作。如果硬件故障或严重的系统错误损坏了 InnoDB数据,MySQL可能会拒绝启动。在这种情况下,请参见第14.21.2节“强制InnoDB恢复”

有关二进制日志和 InnoDB崩溃恢复的信息,请参见 第5.4.4节“二进制日志”

在崩溃恢复期间的表空间发现

如果在恢复过程中InnoDB遇到自上次检查点以来写入的重做日志,则必须将重做日志应用于受影响的表空间。在恢复过程中识别受影响的表空间的过程称为 表空间发现

通过扫描从最后一个检查点到日志末尾的重做日志,可以执行表空间发现,以查找 MLOG_FILE_NAME修改表空间页面时写入的记录。一条 MLOG_FILE_NAME记录包含表空间空间ID和文件名。

在启动时,InnoDB打开系统表空间和重做日志。如果自上次检查点以来写入了重做日志记录,则会根据MLOG_FILE_NAME记录打开受影响的表空间文件

MLOG_FILE_NAME 记录是针对所有持久表空间类型编写的,包括文件每表表空间,常规表空间,系统表空间和撤消日志表空间。

基于重做日志的发现具有以下特征:

  • *.ibd访问自上一个检查点以来修改的表空间文件。

  • 当应用重做日志时*.ibd,未附加到InnoDB实例的 表空间文件将被忽略。

  • 如果MLOG_FILE_NAME系统表空间的记录与影响系统表空间数据文件名的服务器配置不匹配,则在应用重做日志之前,恢复将失败,并显示错误。

  • 如果日志的扫描部分中引用的表空间文件丢失,则启动将被拒绝。

  • *.ibd 只有MLOG_FILE_DELETE在日志中存在文件删除重做日志记录()时,才会忽略 丢失的表空间文件的重做日志。例如,表重命名失败可能导致没有记录丢失 *.ibd文件MLOG_FILE_DELETE在这种情况下,您可以手动重命名表空间文件并重新启动崩溃恢复,也可以使用该innodb_force_recovery 选项以恢复模式重新启动服务器 *.ibd当服务器在恢复模式下启动时,忽略丢失的文件。

在MySQL 5.7中引入的基于重做日志的发现替代了早期MySQL版本中使用的目录扫描,以构建应用重做日志所需空间ID到表空间文件名映射。

14.19 InnoDB和MySQL复制

MySQL的复制适用InnoDBMyISAM表格。还有可能以从机上的存储引擎与主机上的原始存储引擎不相同的方式使用复制。例如,可以InnoDB将对主服务器上的MyISAM表的修改复制到从服务器 上的 表上。有关更多信息,请参见第16.3.3节“在不同的主存储引擎和从属存储引擎中使用复制”

有关为主站设置新从站的信息,请参见 第16.1.2.5节“设置复制从站”以及 第16.1.2.4节“为数据快照选择方法”要创建新的从服务器而不关闭主服务器或现有的从服务器,请使用 MySQL企业备份产品。

在主服务器上失败的事务根本不影响复制。MySQL复制基于MySQL写入修改数据的SQL语句的二进制日志。失败的事务(例如,由于外键违规或因为它被回退)不会写入二进制日志,因此它不会发送到从属设备。请参见第13.3.1节“START TRANSACTION,COMMIT和ROLLBACK语法”

复制和CASCADE。 只有当共享外键关系的表在主控和从属上使用 时,主控InnoDB上的表的 级联动作才会复制到从控制器上。无论您是使用基于语句的还是基于行的复制,情况都是如此。假设您已经开始复制,然后使用以下语句在主服务器上创建两个表 InnoDBCREATE TABLE

CREATE TABLE fc1(
    我INT主键,
    j INT
)ENGINE = InnoDB;

CREATE TABLE fc2(
    m INT主键,
    INT,
    外键ni(n)参考文献fc1(i)
        ON DELETE CASCADE
)ENGINE = InnoDB;

假设从站没有InnoDB 启用支持。如果是这种情况,则创建从属表上的表,但它们使用MyISAM存储引擎,并FOREIGN KEY忽略选项。现在我们在主表中插入一些行:

高手> INSERT INTO fc1 VALUES (1, 1), (2, 2);
查询OK,2行受影响(0.09秒)
记录:2重复:0警告:0

高手> INSERT INTO fc2 VALUES (1, 1), (2, 2), (3, 1);
查询OK,3行受影响(0.19秒)
记录:3重复:0警告:0

此时,在主设备和从设备上,表格 fc1包含2行,表格 fc2包含3行,如下所示:

高手> SELECT * FROM fc1;
+ --- + ------ +
| 我| j |
+ --- + ------ +
| 1 | 1 |
| 2 | 2 |
+ --- + ------ +
设置2行(0.00秒)

高手> SELECT * FROM fc2;
+ --- + ------ +
| m | n |
+ --- + ------ +
| 1 | 1 |
| 2 | 2 |
| 3 | 1 |
+ --- + ------ +
设置3行(0.00秒)

从> SELECT * FROM fc1;
+ --- + ------ +
| 我| j |
+ --- + ------ +
| 1 | 1 |
| 2 | 2 |
+ --- + ------ +
设置2行(0.00秒)

从> SELECT * FROM fc2;
+ --- + ------ +
| m | n |
+ --- + ------ +
| 1 | 1 |
| 2 | 2 |
| 3 | 1 |
+ --- + ------ +
设置3行(0.00秒)

现在假设你DELETE在master上执行以下 语句:

高手> DELETE FROM fc1 WHERE i=1;
查询OK,1行受影响(0.09秒)

由于级联,fc2主站上的表现在只包含1行:

高手> SELECT * FROM fc2;
+ --- + --- +
| m | n |
+ --- + --- +
| 2 | 2 |
+ --- + --- +
一排(0.00秒)

但是,级联不会在从属设备上传播,因为在从属设备上DELETE用于 fc1从中删除行fc2奴隶的副本fc2仍然包含最初插入的所有行:

从> SELECT * FROM fc2;
+ --- + --- +
| m | n |
+ --- + --- +
| 1 | 1 |
| 3 | 1 |
| 2 | 2 |
+ --- + --- +
设置3行(0.00秒)

这种差异是由于级联删除是由InnoDB存储引擎内部处理的,这意味着没有任何更改被记录。

14.20 InnoDB memcached插件

InnoDB 分布式缓存插件(daemon_memcached)提供了一个集成 的memcached守护程序自动存储和检索从数据InnoDB表,把MySQL服务器到快速键值存储您可以使用简单的getsetincr操作来避免与SQL解析和构建查询优化计划相关的性能开销,而 不是使用SQL来制定查询 InnoDB为了方便,复杂的查询,批量操作以及传统数据库软件的其他优势,您还可以通过SQL 访问相同的 表。

这个NoSQL样式接口使用 memcached API来加速数据库操作,让它InnoDB使用缓冲池机制来处理内存缓存 通过修改的数据分布式缓存操作,诸如 addset以及 incr被存储到磁盘,在 InnoDB表中。的组合 分布式缓存的简单性和 InnoDB可靠性和一致性提供两全其美的用户,如在解释 第14.20.1“InnoDB的的好处的memcached插件”有关架构概述,请参阅第14.20.2节“InnoDB memcached体系结构”

14.20.1 InnoDB memcached插件的优点

本节概述了daemon_memcached插件的优点 InnoDB表和memcached的组合 提供了优于单独使用的优势。

  • 直接访问InnoDB存储引擎避免了SQL的解析和计划开销。

  • 在与MySQL服务器相同的进程空间中 运行memcached避免了来回传递请求的网络开销。

  • 使用memcached协议编写的数据透明地写入InnoDB 表中,而无需通过MySQL SQL层。在更新非关键数据时,您可以控制写入频率以实现更高的原始性能。

  • 通过memcached 协议请求的数据可以透明地从InnoDB表中查询 ,而无需通过MySQL SQL层。

  • 随后对相同数据的请求由 InnoDB缓冲池提供。缓冲池处理内存中的缓存。您可以使用InnoDB 配置选项来调整数据密集型操作的性能

  • 数据可以是非结构化或结构化的,这取决于应用程序的类型。您可以为数据创建新表,或使用现有表。

  • InnoDB可以处理将多个列值组合和分解为单个 memcached项目值,从而减少应用程序中所需的字符串解析和串联量。例如,可以将字符串值存储 2|4|6|8memcached 缓存中,并InnoDB根据分隔符分割值,然后将结果存储在四个数字列中。

  • 内存和磁盘之间的传输是自动处理的,简化了应用程序逻辑。

  • 数据存储在MySQL数据库中以防止崩溃,中断和损坏。

  • 您可以InnoDB通过SQL 访问基础表以进行报告,分析,即席查询,批量加载,多步事务计算,集合操作(​​如联合和交集)以及其他适合SQL表现力和灵活性的操作。

  • 您可以通过将主服务器daemon_memcached插件 与MySQL复制结合使用来确保高可用性

  • memcached与MySQL 的集成提供了一种使内存中的数据持久化的方法,因此您可以将它用于更重要的数据类型。您可以使用更多 addincr在您的应用程序,以及类似的写操作,而不用担心数据丢失。您可以停止并启动 memcached服务器,而不会丢失对缓存数据的更新。为防止意外中断,您可以利用InnoDB崩溃恢复,复制和备份功能。

  • 该方法InnoDB确实快速 的主键查找是天作之合memcached的单项查询。daemon_memcached插件使用的直接,低级数据库访问路径对于键值查找而言比等效的SQL查询效率更高。

  • memcached 的序列化功能可以将复杂的数据结构,二进制文件甚至代码块转换为可存储的字符串,提供了一种简单的方法将这些对象存入数据库。

  • 因为你可以通过SQL访问底层数据,可以生成报告,在多个搜索键或更新,并调用功能,如AVG()MAX()memcached的数据。所有这些操作本身使用memcached都很昂贵或复杂

  • 您不需要在启动时手动将数据加载到 memcached中。由于应用程序请求特定的键,因此会自动从数据库中检索值,并使用InnoDB 缓冲池将其缓存到内存中

  • 因为memcached消耗的CPU相对较少,并且其内存占用容易控制,所以它可以在同一系统上与MySQL实例一起轻松运行。

  • 由于数据一致性是由用于常规InnoDB的机制执行的,因此您不必担心失效 memcached数据或备用逻辑在缺少密钥的情况下查询数据库。

14.20.2 InnoDB memcached架构

InnoDB 分布式缓存插件实现的memcached作为访问一个MySQL插件守护程序InnoDB直接存储引擎,绕过MySQL的SQL层。

下图说明了daemon_memcached与SQL相比,应用程序通过插件访问数据的方式

图14.1带有集成memcached服务器的MySQL 服务器

显示使用SQL和memcached协议访问InnoDB存储引擎中的数据的应用程序。 使用SQL,应用程序通过MySQL服务器和Handler API访问数据。 使用memcached协议,应用程序绕过MySQL服务器,通过memcached插件和InnoDB API访问数据。 memcached插件由innodb_memcache接口和可选的本地缓存组成。

该功能daemon_memcached插件:

  • memcached作为 mysqld的守护进程插件 这两个 mysqldmemcached的在同一个进程空间中运行,具有非常低的延迟对数据的访问。

  • 直接访问InnoDB表,绕过SQL解析器,优化器甚至Handler API层。

  • 标准memcached协议,包括基于文本的协议和二进制协议。daemon_memcached插件通过memcapable 命令的所有55个兼容性测试

  • 多列支持。您可以将多个列映射到 键/值存储部分,列值由用户指定的分隔符分隔。

  • 默认情况下,memcached协议用于直接读取和写入数据InnoDB,让MySQL使用InnoDB 缓冲池管理内存中的缓存 默认设置表示高可靠性和数据库应用程序最少意外的组合。例如,默认设置可避免数据库端的未提交数据或返回的陈旧数据 memcached get请求

  • 高级用户可以将系统配置为传统的 memcached服务器,所有数据仅在memcached引擎中缓存(内存缓存),或者结合使用 memcached引擎(内存缓存)和InnoDB memcached引擎(InnoDB 作为后端持久性存储)。

  • 控制多久数据来回传递之间 InnoDBmemcached的 通过操作 innodb_api_bk_commit_intervaldaemon_memcached_r_batch_size以及 daemon_memcached_w_batch_size 配置选项。批量大小选项的默认值为1以实现最大可靠性。

  • 通过 配置参数 指定memcached选项的功能 daemon_memcached_option例如,您可以更改memcached侦听的端口,减少同时连接的最大数量,更改某个键/值对的最大内存大小,或为错误日志启用调试消息。

  • innodb_api_trx_level 配置选项控制事务 隔离级别上通过处理的查询分布式缓存尽管 memcached没有事务的概念 ,但您可以使用此选项来控制memcached多久 可以看到由daemon_memcached插件使用的表上发出的SQL语句导致的更改 默认情况下, innodb_api_trx_level设置为READ UNCOMMITTED

  • innodb_api_enable_mdl 选项可用于在MySQL级锁定表,以便映射表不能通过SQL接口DDL删除或更改 没有锁定,表可以从MySQL层中删除,但保存在InnoDB存储中,直到 memcached或其他用户停止使用它。MDL代表元数据锁定

InnoDB memcached与传统memcached之间的差异

您可能已经熟悉使用 memcached的使用MySQL,如在 使用MySQL与memcached的本节介绍集成的InnoDB memcached插件的功能与传统的不同 memcached

  • 安装:Memcached库随MySQL服务器一起提供,使安装和设置相对简单。安装包括运行 innodb_memcached_config.sql脚本demo_testmemcached创建一个来使用,发布一个 INSTALL PLUGIN语句来启用该daemon_memcached插件,并将所需的memcached选项添加到MySQL配置文件或启动脚本中。您仍然可以安装传统的memcached 发行版,以使用其他实用程序,例如 memcpmemcatmemcapable

    为了与传统的memcached进行比较 ,请参阅 安装memcached

  • 部署:使用传统的memcached,通常会运行大量的低容量 memcached服务器。daemon_memcached然而,插件的典型部署涉及少量已经运行MySQL的中等或高性能服务器。这种配置的好处是提高单个数据库服务器的效率,而不是利用未使用的内存或在大量服务器上分布查找。在默认配置中,memcached只使用很少的内存 ,而内存中的查找则由InnoDB 缓冲池提供,它会自动缓存最近使用频繁使用的数据。和传统的MySQL服务器实例一样,保持innodb_buffer_pool_size 配置选项的值 尽可能高(不会在操作系统级别导致分页),以便在内存中执行尽可能多的工作。

    为了与传统的memcached进行比较 ,请参阅 memcached部署

  • 到期:默认情况下(即使用 innodb_only缓存策略),InnoDB表中的最新数据总是被返回,因此到期选项没有实际影响。如果您将缓存策略更改为cachingcache-only,则过期选项照常工作,但如果在基础表中从内存高速缓存到期之前更新了所请求的数据,则所请求的数据可能过时。

    为了与传统的memcached进行比较 ,请参阅 Data Expiry

  • 命名空间:memcached就像一个大型的目录,在这个目录下,你可以使用前缀和后缀给文件精心制作名称,以防止文件发生冲突。daemon_memcached插件允许您使用类似的密钥命名约定,并增加一个。格式中的键名 被解码以使用来自 表格的映射数据来引用特定的表格。@@table_id.keytable_idinnodb_memcache.containerskey被查找或写入到指定的表。

    @@符号只适用于个别呼叫getaddset功能,而不是其他如 incrdelete要为会话中的后续memcached操作指定默认表, get请使用@@带有符号的表示法 执行请求 table_id但没有键部分例如:

    获取@@table_id
    

    随后getsetincrdelete,等操作使用由指定的表 table_idinnodb_memcache.containers.name 列。

    为了与传统的memcached进行比较 ,请参阅 使用命名空间

  • 散列和分发:使用innodb_only高速缓存策略的默认配置适用于所有服务器(例如一组复制从服务器)上都有所有数据的传统部署配置。

    如果您物理分割数据(如分片配置),则可以在运行daemon_memcached插件的多台计算机上拆分数据,并使用传统的memcached哈希机制将请求路由到特定的计算机。在MySQL方面,您通常会让所有数据按add请求插入 memcached中以便将适当的值存储在相应服务器上的数据库中。

    为了与传统的memcached进行比较 ,请参阅 memcached散列/分布类型

  • 内存使用情况:缺省情况下(使用 innodb_only缓存策略), memcached协议会向InnoDB传递信息InnoDB缓冲池处理内存查找,而不是memcached内存使用量增长和收缩。memcached使用的内存相对较少

    如果将缓存策略切换为 cachingcache-only,则适用memcached内存使用的正常规则memcached数据值的内存按照slabs分配您可以控制用于memcached的平板大小和最大内存

    无论使用哪种方式,您都可以daemon_memcached使用熟悉的统计系统监视和排除插件问题 ,例如,通过标准协议通过Telnet会话访问 插件 daemon_memcached插件不包含额外的实用程序 您可以使用该 memcached-tool 脚本安装完整的memcached 分发。

    为了与传统的比较 memcached的,见 内内存分配的memcached

  • 线程使用情况:MySQL线程和memcached 线程共存于同一台服务器上。操作系统对线程施加的限制适用于线程总数。

    为了与传统的memcached进行比较 ,请参阅 memcached线程支持

  • 日志的使用:由于memcached的守护程序同时运行MySQL服务器和写入 stderr-v-vv-vvv选项日志输出写入MySQL的 错误日志

    为了与传统的memcached进行比较 ,请参阅 memcached Logs

  • memcached的操作:熟悉 memcached的操作,例如 getsetadd,和delete可用。序列化(即,表示复杂数据结构的确切字符串格式)取决于语言界面。

    为了与传统的memcached进行比较 ,请参阅 基本memcached操作

  • 使用memcached作为MySQL前端:这是InnoDB memcached插件的主要目的集成的 memcached守护进程提高了应用程序的性能,并InnoDB处理内存和磁盘之间的数据传输,从而简化了应用程序逻辑。

    为了与传统的memcached进行比较 ,请参阅 memcached用作MySQL缓存层

  • 实用程序:MySQL服务器包含该libmemcached库,但不包括 其他命令行实用程序。要使用诸如 memcpmemcatmemcapable命令之类的命令,请安装完整的 memcached分发。memrmmemflush 从缓存中删除项目时,项目也会从基础InnoDB表中删除

    为了与传统的memcached进行比较 ,请参阅 libmemcached命令行实用程序

  • 编程接口:您可以daemon_memcached使用所有支持的语言通过插件访问MySQL服务器C和C ++JavaPerlPythonPHPRuby像传统的memcached服务器一样指定服务器主机名和端口 默认情况下, daemon_memcached插件在端口上侦听 11211您可以使用 文本和二进制协议您可以自定义 行为运行时的 memcached函数。序列化(即,表示复杂数据结构的确切字符串格式)取决于语言界面。

    为了与传统的memcached进行比较 ,请参阅 开发memcached应用程序

  • 常见问题:MySQL对传统的memcached有广泛的FAQ 除了使用InnoDB 表格作为memcached 数据的存储介质之外,常见问题解答最适用,这意味着您可以将memcached用于比以前更多的写入密集型应用程序,而不是只读缓存。

    请参阅memcached FAQ

14.20.3设置InnoDB memcached插件

本节介绍如何daemon_memcached在MySQL服务器上设置 插件。由于memcached守护进程与MySQL服务器紧密集成以避免网络流量并将延迟降至最低,因此您在使用此功能的每个MySQL实例上执行此过程。

注意

在设置daemon_memcached 插件之前,请参阅第14.20.4节“InnoDB memcached插件的安全注意事项”以了解防止未授权访问所需的安全步骤。

先决条件

  • daemon_memcached插件仅在Linux,Solaris和OS X平台上受支持。其他操作系统不受支持。

  • 从源代码构建MySQL时,必须使用 -DWITH_INNODB_MEMCACHED=ON这个构建选项会在MySQL插件目录(plugin_dir)中生成两个运行daemon_memcached 插件所需的共享库

    • libmemcached.soMySQL memcached守护进程插件。

    • innodb_engine.so:一个memcachedInnoDBAPI插件

  • libevent 必须安装。

    • 如果您没有从源代码构建MySQL,则该 libevent库不包含在您的安装中。使用适用于您的操作系统的安装方法安装libevent 1.4.12或更高版本。例如,根据操作系统,您可以使用apt-getyumport install例如,在Ubuntu Linux上,使用:

      sudo apt-get install libevent-dev
      
    • 如果您从源代码版本安装MySQL,则 libevent1.4.12将与该软件包捆绑在一起,并位于MySQL源代码目录的顶层。如果您使用捆绑版本 libevent,则无需执行任何操作。如果要使用本地系统版本 libevent,则必须使用-DWITH_LIBEVENT设置为system构建选项构建MySQL yes

安装和配置InnoDB memcached插件

  1. 通过运行位于的 配置脚本 daemon_memcached 配置插件,以便它可以与InnoDB交互该脚本安装 有三个需要的表数据库(,和 )。它还将示例表安装 数据库中。 innodb_memcached_config.sqlMYSQL_HOME/shareinnodb_memcachecache_policiesconfig_optionscontainersdemo_testtest

    MySQL的> source MYSQL_HOME/share/innodb_memcached_config.sql
    

    运行innodb_memcached_config.sql 脚本是一次性操作。如果稍后卸载并重新安装该daemon_memcached插件,表格将保留在原位

    mysql> USE innodb_memcache;
    mysql>SHOW TABLES;
    + --------------------------- +
    | Tables_in_innodb_memcache |
    + --------------------------- +
    | cache_policies |
    | config_options |
    | 容器|
    + --------------------------- +
    
    mysql> USE test;
    mysql>SHOW TABLES;
    + ---------------- +
    | Tables_in_test |
    + ---------------- +
    | demo_test |
    + ---------------- +
    

    在这些表格中, innodb_memcache.containers表格是最重要的。containers 表中的条目提供了对InnoDB表格列的映射InnoDBdaemon_memcached插件一起使用的每个表都 需要在containers表中输入一个条目

    innodb_memcached_config.sql脚本在containers 表格中插入单个条目,为表格提供映射 demo_test它还将一行数据插入demo_test表中。这些数据可让您在安装完成后立即验证安装。

    MySQL的> SELECT * FROM innodb_memcache.containers\G
    *************************** 1. row ******************** *******
                      名称:aaa
                 db_schema:测试
                  db_table:demo_test
               key_columns:c1
             value_columns:c2
                     标志:c3
                cas_column:c4
        expire_time_column:c5
    unique_idx_name_on_key:PRIMARY
    
    MySQL的> SELECT * FROM test.demo_test;
    + ---- + ------------------ + ------ + ------ + ------ +
    | c1 | c2 | c3 | c4 | c5 |
    + ---- + ------------------ + ------ + ------ + ------ +
    | AA | HELLO,HELLO | 8 | 0 | 0 |
    + ---- + ------------------ + ------ + ------ + ------ +
    

    有关innodb_memcache表和 demo_test示例表的更多信息 ,请参见 第14.20.7节“InnoDB memcached插件内部”

  2. daemon_memcached通过运行INSTALL PLUGIN 语句来 激活插件

    MySQL的> INSTALL PLUGIN daemon_memcached soname "libmemcached.so";
    

    一旦插件安装完成,每次MySQL服务器重新启动时它都会自动激活。

验证InnoDB和memcached安装程序

要验证daemon_memcached插件设置,请使用telnet会话发出 memcached命令。默认情况下, memcached守护程序在端口11211上侦听。

  1. test.demo_test 表中检索数据demo_test表格中的单行数据 具有键值 AA

    telnet localhost 11211
    尝试127.0.0.1 ...
    连接到本地主机。
    转义字符是'^]'。
    get AA
    价值AA 8 12
    你好你好
    结束
    
  2. 使用set命令插入数据

    set BB 10 0 16
    GOODBYE, GOODBYE
    STORED
    

    哪里:

    • set 是存储值的命令

    • BB 是关键

    • 10是该行动的一面旗帜; memcached忽略,但可能被客户用来指示任何类型的信息; 指定0是否未使用

    • 0是到期时间(TTL); 指定0是否未使用

    • 16 是所提供的值块的字节长度

    • GOODBYE, GOODBYE 是存储的值

  3. 通过连接到MySQL服务器并查询test.demo_test表,验证插入的数据是否存储在MySQL 中。

    MySQL的> SELECT * FROM test.demo_test;
    + ---- + ------------------ + ------ + ------ + ------ +
    | c1 | c2 | c3 | c4 | c5 |
    + ---- + ------------------ + ------ + ------ + ------ +
    | AA | HELLO,HELLO | 8 | 0 | 0 |
    | BB | GOODBYE,GOODBYE | 10 | 1 | 0 |
    + ---- + ------------------ + ------ + ------ + ------ +
    
  4. 返回到Telnet会话并使用密钥检索先前插入的数据BB

    get BB
    价值BB 10 16
    GOODBYE,GOODBYE
    结束
    quit
    

如果您关闭了也关闭集成的memcached服务器的MySQL服务器,则进一步访问memcached数据的尝试会失败,并显示连接错误。通常情况下,memcached 数据在这一点上也会消失,当memcached重新启动时,您需要应用程序逻辑将数据加载回内存 但是, InnoDB memcached插件会为您自动执行此过程。

当您重新启动MySQL时,get操作会再次返回您在先前的memcached会话中存储的键/值对 当请求一个关键字并且关联的值尚未存在于内存高速缓存中时,该值将自动从MySQL test.demo_test表中查询

创建新的表格和列映射

这个例子展示了如何InnoDBdaemon_memcached插件设置你自己的 表格

  1. 创建一个InnoDB表。该表必须具有唯一索引的键列。城市表的关键列是city_id,它被定义为主键。该表还必须包括列 flagscasexpiry值。可能有一个或多个值列。city表有三个值列(namestatecountry)。

    注意

    对于列名,没有特别的要求,因为有效的映射被添加到 innodb_memcache.containers表中。

    mysql> CREATE TABLE city (
           city_id VARCHAR(32),
           name VARCHAR(1024),
           state VARCHAR(1024),
           country VARCHAR(1024),
           flags INT,
           cas BIGINT UNSIGNED, 
           expiry INT,
           primary key(city_id)ENGINE=InnoDB;
    
  2. innodb_memcache.containers表中添加一个条目, 以便daemon_memcached插件知道如何访问InnoDB表。该条目必须满足innodb_memcache.containers 表格定义。有关每个字段的说明,请参见 第14.20.7节“InnoDB memcached插件内部”

    MySQL的> DESCRIBE innodb_memcache.containers;
    + ------------------------ + -------------- + ------ +  - --- + --------- + ------- +
    | 字段| 类型| 空| Key | 默认| 额外|
    + ------------------------ + -------------- + ------ +  - --- + --------- + ------- +
    | 名称| varchar(50)| NO | PRI | NULL | |
    | db_schema | varchar(250)| NO | | NULL | |
    | db_table | varchar(250)| NO | | NULL | |
    | key_columns | varchar(250)| NO | | NULL | |
    | value_columns | varchar(250)| 是| | NULL | |
    | flags | varchar(250)| NO | | 0 | |
    | cas_column | varchar(250)| 是| | NULL | |
    | expire_time_column | varchar(250)| 是| | NULL | |
    | unique_idx_name_on_key | varchar(250)| NO | | NULL | |
    + ------------------------ + -------------- + ------ +  - --- + --------- + ------- +
    

    innodb_memcache.containers全市表表项被定义为:

    MySQL的> INSERT INTO `innodb_memcache`.`containers` (
           `name`, `db_schema`, `db_table`, `key_columns`, `value_columns`,
           `flags`, `cas_column`, `expire_time_column`, `unique_idx_name_on_key`)
           VALUES ('default', 'test', 'city', 'city_id', 'name|state|country', 
           'flags','cas','expiry','PRIMARY');
    
    • default是为该containers.name指定的,将该 city配置InnoDB与该daemon_memcached插件一起使用的默认

    • InnoDB表列(namestatecountry)映射到 containers.value_columns使用 | 分隔符。

    • flagscas_column以及 expire_time_column该领域 innodb_memcache.containers表通常不使用的应用程序显著 daemon_memcached插件。但是,每个指定的InnoDB表格列都是必需的。插入数据时,0为这些列指定 它们是否未使用。

  3. 更新 innodb_memcache.containers表格后,重新启动daemon_memcache插件以应用更改。

    MySQL的> UNINSTALL PLUGIN daemon_memcached;
    
    MySQL的> INSTALL PLUGIN daemon_memcached soname "libmemcached.so";
    
  4. 使用telnet,city 使用memcached set命令将数据插入表中

    telnet localhost 11211
    尝试127.0.0.1 ...
    连接到本地主机。
    转义字符是'^]'。
    set B 0 0 22
    BANGALORE|BANGALORE|IN
    STORED
    
  5. 使用MySQL,查询test.city表格以验证您插入的数据是否已存储。

    MySQL的> SELECT * FROM test.city;
    + --------- + ----------- ----------- + + --------- + ----- -  + ------ + -------- +
    | city_id | 名称| 状态| 国家| flags | cas | 到期|
    + --------- + ----------- ----------- + + --------- + ----- -  + ------ + -------- +
    | B | BANGALORE | BANGALORE | IN | 0 | 3 | 0 |
    + --------- + ----------- ----------- + + --------- + ----- -  + ------ + -------- +
    
  6. 使用MySQL,将附加数据插入 test.city表中。

    mysql> INSERT INTO city VALUES ('C','CHENNAI','TAMIL NADU','IN', 0, 0 ,0);
    mysql> INSERT INTO city VALUES ('D','DELHI','DELHI','IN', 0, 0, 0);
    mysql> INSERT INTO city VALUES ('H','HYDERABAD','TELANGANA','IN', 0, 0, 0);
    mysql>INSERT INTO city VALUES ('M','MUMBAI','MAHARASHTRA','IN', 0, 0, 0);
    
    注意

    建议您0为“ flagscas_column”和“ expire_time_column字段” 指定值( 如果它们未被使用)。

  7. 使用telnet,发出一个memcached get命令来检索你使用MySQL插入的数据。

    get H
    值H 0 22
    海得拉巴|特兰伽纳| IN
    结束
    

配置InnoDB memcached插件

传统memcached配置选项可以 配置参数的参数中编码的MySQL配置文件或 mysqld启动字符串中 daemon_memcached_option指定。memcached 配置选项在加载插件时生效,每次启动MySQL服务器时都会发生这种情况。

例如,要使memcached在端口11222而不是默认端口11211上侦听,请指定 -p11222daemon_memcached_option 配置选项的参数

mysqld .... --daemon_memcached_option =“ -  p11222”

其他memcached选项可以在daemon_memcached_option字符串中编码 例如,可以指定选项以减少同时连接的最大数量,更改键/值对的最大内存大小,或为错误日志启用调试消息等等。

还有特定于该daemon_memcached插件的配置选项 这些包括:

  • daemon_memcached_engine_lib_name:指定实现InnoDB memcached 插件的共享库 默认设置是 innodb_engine.so

  • daemon_memcached_engine_lib_path:包含实现InnoDB memcached插件的共享库的目录的路径缺省值为NULL,表示插件目录。

  • daemon_memcached_r_batch_size:定义读操作(get的批量落实大小它指定发生提交之后memcached读取操作 的数量 默认情况下设置为1,以便每个 请求都可以访问表中最近提交的数据 ,不管数据是通过memcached还是通过SQL 更新的当该值大于1时,读取操作的计数器随每次调用而增加一个 调用重置读取和写入计数器。 daemon_memcached_r_batch_sizegetInnoDBgetflush_all

  • daemon_memcached_w_batch_size:定义批提交大小写操作(setreplaceappendprependincrdecr,等)。 daemon_memcached_w_batch_size 默认情况下设置为1,以便在发生中断时不丢失未提交的数据,并且使得基础表上的SQL查询访问最近的数据。当该值大于1时,用于写入操作的计数器被递增为每个addsetincrdecr,和delete调用。一个flush_all调用重置读取和写入计数器。

默认情况下,您不需要修改 daemon_memcached_engine_lib_namedaemon_memcached_engine_lib_path例如,如果您想要为memcached使用不同的存储引擎 (例如NDB memcached引擎),则可以配置这些选项

daemon_memcached插件配置参数可以在MySQL配置文件或mysqld启动字符串中指定。它们在加载daemon_memcached插件时生效

在更改daemon_memcached 插件配置时,请重新加载插件以应用更改。为此,请发出以下声明:

MySQL的> UNINSTALL PLUGIN daemon_memcached;

MySQL的> INSTALL PLUGIN daemon_memcached soname "libmemcached.so";

配置设置,所需表格和数据在插件重新启动时被保留。

有关启用和禁用插件的更多信息,请参见第5.5.1节“安装和卸载插件”

14.20.4 InnoDB memcached插件的安全注意事项

警告

daemon_memcached在生产服务器上 部署插件之前,或者在MySQL实例包含敏感数据的情况下甚至在测试服务器上部署插件之前,请先参考此部分

由于默认情况下memcached不使用身份验证机制,并且可选SASL身份验证不像传统DBMS安全措施那样强壮,所以仅在使用该daemon_memcached插件的MySQL实例中保留非敏感数据,并隔离使用此配置的任何服务器来自潜在的入侵者。不要允许memcached从Internet访问这些服务器; 只允许在防火墙内部网中访问,理想情况下是从您可以限制其成员资格的子网访问。

密码保护memcached使用SASL

SASL支持提供了通过memcached客户端保护您的MySQL数据库免受未经身份验证访问的能力 本节介绍如何使用daemon_memcached 插件启用S​​ASL 这些步骤与为传统的memcached 服务器启用S​​ASL所执行的步骤几乎完全相同

SASL代表简单认证和安全层,这是为基于连接的协议添加认证支持的标准。memcached在版本1.4.3中增加了SASL支持。

SASL认证仅支持二进制协议。

memcached客户端只能访问在 InnoDB表中注册的 innodb_memcache.containers表。尽管DBA可以对这些表设置访问限制,但无法控制通过 memcached应用程序访问出于这个原因,SASL支持被提供来控制对InnoDBdaemon_memcached插件关联的表的访问

以下部分显示如何构建,启用和测试支持SASL的daemon_memcached插件。

使用InnoDB memcached插件构建和启用SASL

默认情况下,支持SASL的daemon_memcached 插件不包含在MySQL发布包中,因为支持SASL的daemon_memcached插件需要使用SASL库构建memcached要启用SASL支持,请下载MySQL源并daemon_memcached在下载SASL库后重新 构建插件:

  1. 安装SASL开发和实用程序库。例如,在Ubuntu上,使用apt-get获取库:

    sudo apt-get -f install libsasl2-2 sasl2-bin libsasl2-2 libsasl2-dev libsasl2-modules
    
  2. daemon_memcached通过添加ENABLE_MEMCACHED_SASL=1cmake选项 构建具有SASL功能插件共享库 memcached还提供简单的明文密码支持,这有助于测试。要启用简单的明文密码支持,请指定ENABLE_MEMCACHED_SASL_PWDB=1 cmake选项。

    总之,添加以下三个cmake 选项:

    cmake ... -DWITH_INNODB_MEMCACHED = 1 -DENABLE_MEMCACHED_SASL = 1 -DENABLE_MEMCACHED_SASL_PWDB = 1
    
  3. daemon_memcached第14.20.3节“设置InnoDB memcached插件”中所述 安装该插件

  4. 配置用户名和密码文件。(这个例子使用 memcached简单明文密码支持。)

    1. 在一个文件中,创建一个名为user testname并定义密码为 testpasswd

      
      echo“testname:testpasswd :::::::”> / home / jy / memcached-sasl-db
      
      
    2. 配置MEMCACHED_SASL_PWDB 环境变量以通知 memcached用户名和密码文件:

      导出MEMCACHED_SASL_PWDB = / home / jy / memcached-sasl-db
      
    3. 通知memcached使用明文密码:

      
      echo“mech_list:plain”> /home/jy/work2/msasl/clients/memcached.conf
      导出SASL_CONF_PATH = / home / jy / work2 / msasl / clients
      
  5. 通过 配置参数中编码memcached -S选项 重新启动MySQL服务器来启用SASL daemon_memcached_option

    mysqld ... --daemon_memcached_option =“ -  S”
    
  6. 要测试设置,请使用支持SASL的客户端,如 启用S​​ASL的libmemcached

    memcp --servers = localhost:11211 --binary --username = testname
      --password = passwordmyfile.txt
    
    memcat --servers = localhost:11211 --binary --username = testname
      --password = passwordmyfile.txt
    

    如果您指定了错误的用户名或密码,则该操作将被拒绝并显示一条memcache error AUTHENTICATION FAILURE消息。在这种情况下,请检查memcached-sasl-db文件中设置的明文密码, 以验证您提供的凭据是否正确。

还有其他方法可以用memcached测试SASL认证 ,但上述方法是最直接的。

14.20.5编写InnoDB memcached插件的应用程序

通常,为InnoDB memcached插件编写应用程序 需要一定程度的重写或修改使用MySQL或memcached API的现有代码

  • 使用daemon_memcached插件,而不是运行在低功率机器上的许多传统memcached服务器,您拥有与MySQL服务器相同数量的 memcached服务器,运行在相对高性能的机器上,并具有大量的磁盘存储和内存。您可能会重用一些与memcached API 配合使用的现有代码,但由于服务器配置不同,可能需要进行适应。

  • 通过daemon_memcached插件存储的数据 进入 VARCHARTEXTBLOB列,并且必须转换为数字操作。您可以在应用程序端执行转换,或者使用CAST()查询中函数。

  • 来自数据库背景,您可能习惯于具有多列的通用SQL表。通过memcached代码访问的表可能只有少数甚至是一列保存数据值。

  • 您可能会调整执行单行查询,插入,更新或删除的应用程序的某些部分,以提高关键代码段的性能。两个 查询(读取)和 DML(写)操作可以通过执行时更快基本上 InnoDB 分布式缓存 接口。写入的性能改进通常大于读取的性能改进,因此您可能会专注于调整执行日志记录或在网站上记录交互式选择的代码。

以下各节将更详细地探讨这些要点。

14.20.5.1调整InnoDB memcached插件的现有MySQL模式

在调整现有MySQL模式或应用程序以使用 插件时, 请考虑memcached应用程序的这些方面daemon_memcached

  • memcached密钥不能包含空格或换行符,因为这些字符在ASCII协议中用作分隔符。如果您使用包含空格的查找值,在调用使用它们作为键来变换前或将它们散列到值没有空格 add()set()get(),等等。尽管理论上这些字符在使用二进制协议的程序中的键中是允许的,但您应该限制键中使用的字符以确保与广泛的客户端兼容。

  • 如果表中存在简短的数字 主键InnoDB,则通过将整数转换为字符串值,将其用作memcached的唯一查找键如果 memcached服务器用于多个应用程序或多个 InnoDB表,请考虑修改名称以确保它是唯一的。例如,在数字值前加上表名,或数据库名和表名。

    注意

    daemon_memcached插件支持插入和读取InnoDB 具有INTEGER定义为主键的映射

  • 对于使用memcached查询或存储的数据,不能使用分区表

  • 分布式缓存协议围绕经过数字值作为字符串。要将数值存储在基础InnoDB表中,要实现可用于SQL函数(如SUM()或)的计数器, AVG()例如:

    • 使用VARCHAR具有足够字符的列来保存最大预期编号的所有数字(以及适用于负号,小数点或两者的附加字符)。

    • 在任何使用列值执行算术的查询中,使用该CAST()函数将字符串中的值转换为整数或其他数字类型。例如:

      #按字母顺序的条目返回为零。
      
      SELECT CAST(c2作为无符号整数)FROM demo_test;
      
      #因为可能有0的数值,所以不能取消它们的资格。
      #测试字符串值来查找那些是整数的值,并且只对这些值进行平均。
      
      SELECT AVG(cast(c2 as unsigned integer))FROM demo_test
        在哪里c2'0'和'9999999999'之间;
      
      #视图让你隐藏查询的复杂性。结果已经被转换;
      #无需每次重复转换函数和WHERE子句。
      
      CREATE VIEW数字AS SELECT c1 KEY,CAST(c2 AS UNSIGNED INTEGER)val
        FROM demo_test WHERE c2 BETWEEN'0'和'9999999999';
      SELECT SUM(val)FROM numbers;
      
      注意

      通过调用将结果集中的任何字母值转换为0 CAST()使用AVG()取决于结果集中行数的函数时,应包含WHERE用于过滤非数字值的子句。

  • 如果InnoDB用作键列的值可能超过250个字节,则将该值散列为小于250个字节。

  • 要在daemon_memcached插件中使用现有的表格,请在表格中 为其定义一个条目innodb_memcache.containers要将该表作为所有memcached请求的缺省 值,请default在该name 列中指定一个值 ,然后重新启动MySQL服务器以使更改生效。如果对不同类别的memcached数据使用多个表格,请innodb_memcache.containers表格中用 name您选择的值设置多个表项 ,然后发出 memcached请求,格式为 get @@nameset @@name 在应用程序中指定要用于后续memcached请求的表

    有关使用预定义test.demo_test以外的 表的示例,请参见 示例14.13,“将自己的表与InnoDB memcached应​​用程序一起使用”有关所需的表格布局,请参见 第14.20.7节“InnoDB memcached插件内部”

  • 要将多个InnoDB表列值与memcached键/值对一起使用,请表格value_columnsinnodb_memcache.containers条目字段中指定用逗号,分号,空格或管道字符分隔的列名称InnoDB例如,指定col1,col2,col3col1|col2|col3在该 value_columns字段中。

    在将字符串传递给memcached addset调用之前,使用管道字符作为分隔符将列值连接成单个字符串 该字符串会自动解压到正确的列中。每个 get调用都会返回一个单独的字符串,其中包含也由管道字符分隔的列值。您可以使用适当的应用程序语言语法解压缩这些值。

例14.13在InnoDB memcached应​​用程序中使用自己的表

此示例显示如何将自己的表与memcached用于数据操作的示例Python应用程序一起使用

该示例假定 daemon_memcached按照第14.20.3节“设置InnoDB memcached插件”中的描述安装插件它还假定您的系统已配置为运行使用该python-memcache模块的Python脚本

  1. 创建multicol存储国家信息表格,包括人口,区域和驾驶员侧数据('R'右侧和 'L'左侧)。

    MySQL的> USE test;
    
    MySQL的> CREATE TABLE `multicol` (
            `country` varchar(128) NOT NULL DEFAULT '',
            `population` varchar(10) DEFAULT NULL,
            `area_sq_km` varchar(9) DEFAULT NULL,
            `drive_side` varchar(1) DEFAULT NULL,
            `c3` int(11) DEFAULT NULL,
            `c4` bigint(20) unsigned DEFAULT NULL,
            `c5` int(11) DEFAULT NULL,
            PRIMARY KEY (`country`)
            ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
    
  2. innodb_memcache.containers表格中插入一条记录, 以便daemon_memcached插件可以访问multicol表格。

    MySQL的> INSERT INTO innodb_memcache.containers
           (name,db_schema,db_table,key_columns,value_columns,flags,cas_column,
           expire_time_column,unique_idx_name_on_key)
           VALUES
           ('bbb','test','multicol','country','population,area_sq_km,drive_side',
           'c3','c4','c5','PRIMARY');
    
    MySQL的> COMMIT;
    
    • innodb_memcache.containers 记录multicol指定了一个name'bbb',它是表标识符。

      注意

      如果InnoDB为所有memcached应用程序使用单个,则name可以将该值设置 default为避免使用 @@表示法来切换表。

    • db_schema列设置为 test,这是multicol表所在的数据库的名称

    • db_table列设置为 multicol,这是名称 InnoDB表。

    • key_columns被设置为唯一 country列。country列被定义为multicol表定义中的主键

    • InnoDB数据被划分为三个表格列(,和 population 而不是单个表格列来存放组合数据值为了适应多个值列,在字段中指定了逗号分隔的列列表 在字段中定义的列是存储或检索值时使用的列。 area_sq_kmdrive_sidevalue_columnsvalue_columns

    • 对值flagsexpire_time以及 cas_column字段基于在所使用的值demo.test的示例表。这些字段在使用daemon_memcached插件的应用程序中通常不重要, 因为MySQL会保持数据同步,并且不需要担心数据过期或过时。

    • unique_idx_name_on_key字段设置为PRIMARY,它引用表中唯一country上定义的主索引 multicol

  3. 将示例Python应用程序复制到文件中。在此示例中,示例脚本被复制到名为的文件中 multicol.py

    示例Python应用程序将数据插入 multicol表中并检索所有键的数据,演示如何InnoDB通过daemon_memcached插件访问

    导入sys,os
    导入memcache
    
    def connect_to_memcached():
      memc = memcache.Client(['127.0.0.1:11211'],debug = 0);
      打印“连接到memcached”。
      返回memc
    
    def banner(message):
      打印
      打印“=”* len(消息)
      打印消息
      打印“=”* len(消息)
    
    country_data = [
    ( “加拿大”, “34820000”, “9984670”, “R”),
    ( “USA”, “314242000”, “9826675”, “R”),
    ( “爱尔兰”, “6399152”, “84421”, “L”),
    ( “英国”, “62262000”, “243610”, “L”),
    ( “墨西哥”, “113910608”, “1972550”, “R”),
    ( “丹麦”, “5543453”, “43094”, “R”),
    ( “挪威”, “5002942”, “385252”, “R”),
    ( “UAE”, “8264070”, “83600”, “R”),
    ( “印”, “1210193422”, “3287263”, “L”),
    ( “中国”, “1347350000”, “9640821”, “R”),
    ]
    
    def switch_table(memc,table):
      键=“@@”+表
      打印“通过为''+ key +''发出GET来将默认表切换为'”+表格+“'”。
      result = memc.get(key)
    
    def insert_country_data(memc):
      横幅(“通过memcached接口插入初始数据”)
      对于country_data中的项目:
        country = item [0]
        人口=项目[1]
        区域=项目[2]
        drive_side = item [3]
    
        键=国家
        value =“|”.join([population,area,drive_side])
        打印“Key =”+键
        打印“值=”+值
    
        如果memc.add(键值):
          打印“添加了新的密钥,值对。”
        其他:
          打印“更新现有密钥的值”。
          memc.set(键,值)
    
    def query_country_data(memc):
      横幅(“检索所有密钥(国家名称)的数据”)
      对于country_data中的项目:
        key = item [0]
        result = memc.get(key)
        打印“这是从数据库中为键”+ key +“检索的结果:”
        打印结果
        (m_population,m_area,m_drive_side)= result.split(“|”)
        打印“解压后的人口值:”+ m_population
        打印“解包区域值:”+ m_area
        打印“解压后的驱动器侧值:”+ m_drive_side
    
    如果__name__ =='__main__':
    
      memc = connect_to_memcached()
      switch_table(MEMC, “BBB”)
      insert_country_data(MEMC)
      query_country_data(MEMC)
    
      sys.exit(0)
    

    示例Python应用笔记:

    • 由于数据操作是通过memcached接口执行的,因此不需要数据库授权来运行应用程序唯一需要的信息是memcached守护程序侦听的本地系统上的端口号

    • 为了确保应用程序使用该 multicol表,switch_table()调用函数,该 函数使用表示法执行虚拟getset请求 @@name请求中值是 字段中定义bbbmulticol表标识符 innodb_memcache.containers.name

      一个更具描述性的name价值可能被用在现实世界的应用程序中。这个例子只是说明了一个表格标识符被指定,而不是get @@...请求中的表格名称

    • 用于插入和查询数据的实用函数演示了如何将Python数据结构转换为管道分隔值,以便将数据发送给MySQL addset 请求,以及如何解开get请求返回的管道分隔值只有在将单个memcached映射到多个MySQL表列时才需要额外处理

  4. 运行示例Python应用程序。

    外壳> python multicol.py
    

    如果成功,示例应用程序将返回此输出:

    连接到memcached。
    通过为'@@ bbb'发布GET来将默认表切换为'bbb'。
    
    ==============================================
    通过memcached接口插入初始数据
    ==============================================
    键=加拿大
    价值= 34820000 | 9984670 | R
    增加了新的键值对。
    键=美国
    值= 314242000 | 9826675 | R
    增加了新的键值对。
    键=爱尔兰
    值= 6399152 | 84421 | L
    增加了新的键值对。
    关键=英国
    值= 62262000 | 243610 | L
    增加了新的键值对。
    关键=墨西哥
    值= 113910608 | 1972550 | R
    增加了新的键值对。
    关键=丹麦
    值= 5543453 | 43094 | R
    增加了新的键值对。
    关键=挪威
    值= 5002942 | 385252 | R
    增加了新的键值对。
    关键=阿联酋
    值= 8264070 | 83600 | R
    增加了新的键值对。
    关键=印度
    值= 1210193422 | 3287263 | L
    增加了新的键值对。
    关键=中国
    值= 1347350000 | 9640821 | R
    增加了新的键值对。
    
    ============================================
    检索所有键(国名)的数据
    ============================================
    以下是加拿大主要数据库的检索结果:
    34820000 | 9984670 | R
    未包装的人口值:34820000
    未包装的面积值:9984670
    未包装的驱动器侧值:R
    以下是美国主要数据库的检索结果:
    314242000 | 9826675 | R
    未包装的人口值:314242000
    未包装的面积值:9826675
    未包装的驱动器侧值:R
    以下是爱尔兰关键数据库的检索结果:
    6399152 | 84421 | L
    未包装的人口值:6399152
    未包装的面积值:84421
    未包装的驱动器侧值:L
    以下是英国主要数据库的检索结果:
    62262000 | 243610 | L
    未包装的人口值:62262000
    未包装的面积值:243610
    未包装的驱动器侧值:L
    以下是墨西哥关键数据库的检索结果:
    113910608 | 1972550 | R
    未包装的人口值:113910608
    未包装的面积值:1972550
    未包装的驱动器侧值:R
    以下是丹麦主要数据库的检索结果:
    5543453 | 43094 | R
    未包装的人口值:5543453
    未包装的面积值:43094
    未包装的驱动器侧值:R
    以下是挪威主要数据库的检索结果:
    5002942 | 385252 | R
    未包装的人口值:5002942
    未包装的面积值:385252
    未包装的驱动器侧值:R
    以下是从数据库中检索的关键阿联酋的结果:
    8264070 | 83600 | R
    未包装的人口值:8264070
    未包装的面积值:83600
    未包装的驱动器侧值:R
    以下是从印度主要数据库中检索的结果:
    1210193422 | 3287263 | L
    未包装的人口值:1210193422
    未包装的面积值:3287263
    未包装的驱动器侧值:L
    这是从关键中国数据库检索的结果:
    1347350000 | 9640821 | R
    未包装的人口值:1347350000
    未包装的面积值:9640821
    未包装的驱动器侧值:R
    
  5. 查询innodb_memcache.containers 表格以查看您之前为multicol表格插入的记录 第一条记录是demo_test在初始daemon_memcached插件安装期间创建的示例条目第二条记录是您为multicol表格插入的条目

    MySQL的> SELECT * FROM innodb_memcache.containers\G
    *************************** 1. row ******************** *******
                      名称:aaa
                 db_schema:测试
                  db_table:demo_test
               key_columns:c1
             value_columns:c2
                     标志:c3
                cas_column:c4
        expire_time_column:c5
    unique_idx_name_on_key:PRIMARY
    *************************** 2. row ******************** *******
                      名称:bbb
                 db_schema:测试
                  db_table:multicol
               key_columns:国家
             value_columns:人口,area_sq_km,drive_side
                     标志:c3
                cas_column:c4
        expire_time_column:c5
    unique_idx_name_on_key:PRIMARY
    
  6. 查询multicol表格以查看示例Python应用程序插入的数据。这些数据可用于MySQL 查询,它演示了如何使用SQL或通过应用程序(使用适当的MySQL连接器或API访问相同的数据

    MySQL的> SELECT * FROM test.multicol;
    + --------- + ------------ + ------------ + ------------ + ------ + ------ + ------ +
    | 国家| 人口| area_sq_km | drive_side | c3 | c4 | c5 |
    + --------- + ------------ + ------------ + ------------ + ------ + ------ + ------ +
    | 加拿大| 34820000 | 9984670 | R | 0 | 11 | 0 |
    | 中国| 1347350000 | 9640821 | R | 0 | 20 | 0 |
    | 丹麦| 5543453 | 43094 | R | 0 | 16 | 0 |
    | 印度| 1210193422 | 3287263 | L | 0 | 19 | 0 |
    | 爱尔兰| 6399152 | 84421 | L | 0 | 13 | 0 |
    | 墨西哥| 113910608 | 1972550 | R | 0 | 15 | 0 |
    | 挪威| 5002942 | 385252 | R | 0 | 17 | 0 |
    | 阿联酋| 8264070 | 83600 | R | 0 | 18 | 0 |
    | 英国| 62262000 | 243610 | L | 0 | 14 | 0 |
    | USA | 314242000 | 9826675 | R | 0 | 12 | 0 |
    + --------- + ------------ + ------------ + ------------ + ------ + ------ + ------ +
    
    注意

    定义被视为数字的列的长度时,始终允许足够的大小以保留必要的数字,小数点,符号字符,前导零等。字符串列(如a)VARCHAR的太长值 会通过删除某些可能产生无意义数字值的字符而被截断。

  7. (可选)在InnoDB存储memcached数据上运行报告类型查询

    您可以通过SQL查询生成报告,跨任何列执行计算和测试,而不仅仅是 country关键列。(因为以下示例仅使用来自少数几个国家/地区的数据,所以这些数字仅用于说明目的。)以下查询返回人们在右侧驾驶的国家的平均人口数,以及名称以U

    MySQL的> SELECT AVG(population) FROM multicol WHERE drive_side = 'R';
    + ------------------- +
    | 平均(人口)|
    + ------------------- +
    | 261304724.7142857 |
    + ------------------- +
    
    MySQL的> SELECT SUM(area_sq_km) FROM multicol WHERE country LIKE 'U%';
    + ----------------- +
    | sum(area_sq_km)|
    + ----------------- +
    | 10153885 |
    + ----------------- +
    

    因为populationarea_sq_km列存储字符数据而不是强类型的数字数据,所以函数(比如AVG()函数 SUM()首先将每个值转换为数字)。这种方法 不适用于诸如<>比较基于字符的值等运算符 9 > 1000,这不是从一个子句中预期的,例如ORDER BY population DESC对于最准确的类型处理,针对将数字列转换为适当类型的视图执行查询。这种技术可以让你发布简单SELECT *查询数据库应用程序,同时确保投射,筛选和排序是正确的。下面的例子显示了一个可以按照人口从高到低的顺序查找前三个国家的视图,其结果反映了multicol表中的最新数据,并将人口和面积数字视为数字:

    MySQL的> CREATE VIEW populous_countries AS
           SELECT
           country,
           cast(population as unsigned integer) population,
           cast(area_sq_km as unsigned integer) area_sq_km,
           drive_side FROM multicol
           ORDER BY CAST(population as unsigned integer) DESC
           LIMIT 3;
    
    MySQL的> SELECT * FROM populous_countries;
    + --------- + ------------ + ------------ + ------------ +
    | 国家| 人口| area_sq_km | drive_side |
    + --------- + ------------ + ------------ + ------------ +
    | 中国| 1347350000 | 9640821 | R |
    | 印度| 1210193422 | 3287263 | L |
    | USA | 314242000 | 9826675 | R |
    + --------- + ------------ + ------------ + ------------ +
    
    MySQL的> DESC populous_countries;
    + ------------ + --------------------- + ------ + ------ +  - -------- ------- + +
    | 字段| 类型| 空| Key | 默认| 额外|
    + ------------ + --------------------- + ------ + ------ +  - -------- ------- + +
    | 国家| varchar(128)| NO | | | |
    | 人口| bigint(10)unsigned | 是| | NULL | |
    | area_sq_km | int(9)unsigned | 是| | NULL | |
    | drive_side | varchar(1)| 是| | NULL | |
    + ------------ + --------------------- + ------ + ------ +  - -------- ------- + +
    

14.20.5.2修改InnoDB memcached插件的memcached应​​用程序

InnoDB 在调整现有的memcached 应用程序以使用daemon_memcached 插件时, 请考虑MySQL和表的这些方面

  • 如果有键值超过几个字节,它可能是更有效地使用数字自动增量列作为 主键的的 InnoDB表格,并创造了独特的 二次指数 在包含列memcached的 键值。这是因为InnoDB 如果主键值以排序顺序添加(因为它们具有自动增量值),则对于大规模插入最适合执行。主键值包含在二级索引中,如果主键是一个长字符串值,则会占用不必要的空间。

  • 如果使用memcached存储多个不同类别的信息 ,请考虑InnoDB为每种类型的数据设置一个单独的 表。innodb_memcache.containers表中定义其他表标识符 ,并使用该 标记来存储和检索不同表中的项目。通过物理划分不同类型的信息,可以调整每个表格的特征以获得最佳空间利用率,性能和可靠性。例如,您可能启用 压缩@@table_id.key对于拥有博客帖子的表格,但对于包含缩略图图像的表格不适用。您可能比另一个表更频繁地备份一个表,因为它保存关键数据。您可以在经常用于使用SQL生成报表的表上创建附加的 二级索引

  • 最好配置一组稳定的表定义以供daemon_memcached插件使用,并永久保留这些表。innodb_memcache.containers下次innodb_memcache.containers查询表格时,表格的更改 会生效 容器表中的条目在启动时处理,并且每当containers.name使用@@符号请求无法识别的表格标识符(由定义的表格 )时将被查询 因此,只要使用关联的表标识符,新条目就可见,但对现有条目的更改需要服务器重新启动才能生效。

  • 当您使用默认的innodb_only 缓存策略,调用add()set()incr(),等能成功,但依旧会触发调试消息如 while expecting 'STORED', got unexpected response 'NOT_STORED调试消息的发生是因为 缓存策略InnoDB导致新值和更新值直接发送到 表而不保存在内存缓存中innodb_only

14.20.5.3调整InnoDB memcached插件性能

因为InnoDBmemcached结合使用 需要将所有数据写入磁盘,不管是立即还是稍后,原始性能预计会比使用memcached本身稍慢 在使用 InnoDB memcached插件时,请注意memcached操作的调优目标,以实现比等效SQL操作更好的性能。

基准测试表明,使用memcached 接口的查询和 DML操作(插入,更新和删除)比传统SQL更快。DML操作通常会看到更大的改进。因此,考虑首先使用写密集型应用程序来使用 memcached接口。还要考虑优先使用缺乏可靠性的快速轻量级机制的写入密集型应用的适应性。

调整SQL查询

最适合简单GET请求的查询类型是子句中包含单个子句或一组AND条件 的查询类型 WHERE

SQL:
SELECT col FROM tbl WHERE key ='key_value';

memcached的:
获得key_value

SQL:
SELECT col FROM tbl WHERE col1 = val1和col2 = val2和col3 = val3;

memcached的:
#因为你必须知道这三个值来查找关键字,
#将它们组合成一个唯一的字符串并将其用作关键字
#用于所有ADD,SET和GET操作。
key_value = val1 +“:”+ val2 +“:”+ val3
获得key_value

SQL:
SELECT'键存在!' 从tbl
  WHERE EXISTS(SELECT col1 FROM tbl WHERE KEY ='key_value')LIMIT 1;

memcached的:
#通过询问其值并检查调用是否成功来测试密钥的存在性,
#忽略值本身。对于存在检查,你通常只存储一个
#短值,例如“1”。
获得key_value
使用系统内存

为了获得最佳性能,请将该daemon_memcached插件部署到 配置为典型数据库服务器的机器上,其中大部分系统RAM 通过 配置选项专用于InnoDB 缓冲池innodb_buffer_pool_size对于具有多吉字节缓冲池的系统,innodb_buffer_pool_instances 当大多数操作涉及已经缓存在内存中的数据时,请考虑提高最大吞吐量的值

减少冗余I / O

InnoDB有许多设置可以让您在发生崩溃时选择高可靠性与高写入工作负载期间的I / O开销量之间的平衡。例如,考虑设置 innodb_doublewrite0innodb_flush_log_at_trx_commit2使用不同的innodb_flush_method设置测量性能

注意

innodb_support_xa已弃用,将在未来版本中删除。从MySQL 5.7.10开始,InnoDB对XA事务中的两阶段提交的支持始终处于启用状态,并且innodb_support_xa不再允许禁用

有关为表操作减少或调整I / O的其他方法,请参见 第8.5.8节“优化InnoDB磁盘I / O”

减少交易开销

的1为默认值 daemon_memcached_r_batch_size ,并 daemon_memcached_w_batch_size 适用于结果的最大的可靠性和存储或更新的数据的安全性。

根据应用程序的类型,您可以增加其中的一个或两个设置以减少频繁提交操作的开销 在繁忙的系统上,您可能会增加 daemon_memcached_r_batch_size,因为知道通过SQL创建的数据更改可能不会立即memcached显示(也就是说,直到 处理了N更多get操作)。处理必须可靠存储每个写入操作的数据时,请将其 daemon_memcached_w_batch_size 设置为1处理大量仅用于统计分析的更新时增加设置,在N崩溃中丢失上次 更新是可接受的风险。

例如,设想一个系统,监控穿过繁忙桥梁的交通情况,每天记录大约100,000辆车的数据。如果应用程序统计不同类型的车辆来分析流量模式,改变 daemon_memcached_w_batch_size1100减少99%提交操作的I / O开销。如果发生故障,最多可丢失100条记录,这可能是一个可接受的误差范围。相反,如果应用程序进行自动收费为每一辆汽车,您将设置 daemon_memcached_w_batch_size1确保每个收费记录被立即保存到磁盘。

由于在磁盘上InnoDB组织 memcached密钥值的方式,如果您有大量密钥要创建,可能会更快地按应用程序中的键值对数据项进行排序,并按 add排序顺序对其进行排序,而不是按任意顺序创建密钥。

memslap命令,这是常规的一部分,分布式缓存分布,但不包含在daemon_memcached插件,可以进行基准测试的不同配置是有用的。它也可以用来生成样本键/值对以用于您自己的基准。有关 详细信息,请参阅 libmemcached命令行实用程序

14.20.5.4控制InnoDB memcached插件的事务行为

不同于传统的分布式缓存,该 daemon_memcached插件可以让你控制通过将呼叫产生的数据值的耐用性 addsetincr,等等。默认情况下,通过memcached接口写入的数据存储到磁盘,并调用get从磁盘返回最新值。尽管默认行为不能提供最佳的原始性能,但与InnoDB表格的SQL接口相比仍然很快

在您获得使用daemon_memcached插件的经验时 ,您可以考虑放宽非关键数据类的耐久性设置,在发生中断时可能丢失一些更新的值,或者返回稍微过时的数据。

提交频率

耐久性和原始性能之间的一个折衷是新数据和更改数据的提交频率 如果数据非常重要,应该立即执行,以便在发生崩溃或中断时安全。如果数据不那么重要,例如在崩溃后重置的计数器或记录您可能会丢失的数据,则可能需要较高的原始吞吐量,而提交的频率较低。

memcached操作插入,更新或删除基础InnoDB 表中的数据时,可能会InnoDB立即(if daemon_memcached_w_batch_size=1)或稍后(如果该 daemon_memcached_w_batch_size 值大于1)将更改提交到 表中 无论哪种情况,更改都无法回滚。如果增加值 daemon_memcached_w_batch_size 以避免繁忙时间内的I / O开销较高,则在工作负载减少时,提交可能会不频繁。作为一项安全措施,后台线程会定期自动提交通过memcached API 进行的更改间隔由...控制 innodb_api_bk_commit_interval 配置选项,其默认设置为 5秒。

memcached操作插入或更新基础InnoDB表中的数据时,更改后的数据对其他memcached请求立即可见, 因为新值仍保留在内存高速缓存中,即使它尚未在MySQL端提交。

事务隔离

当一个memcached操作(例如 getincr在底层InnoDB上导致查询或DML操作)时,您可以控制操作是否会看到写入表中的最新数据,只有已提交的数据或事务隔离级别的其他变体 使用innodb_api_trx_level 配置选项来控制此功能。为此选项指定的数值对应于隔离级别,例如 REPEATABLE READinnodb_api_trx_level有关其他设置的信息,请参阅该选项的说明

严格的隔离级别可确保您检索的数据不会回滚或突然更改,从而导致后续查询返回不同的值。但是,严格的隔离级别要求更高的锁定 开销,这可能导致等待。对于不使用长时间运行的事务的NoSQL样式的应用程序,通常可以使用默认隔离级别或切换到不太严格的隔离级别。

为memcached DML操作禁用行锁

innodb_api_disable_rowlock通过插件的memcached请求 daemon_memcached导致DML操作时,选项可用于禁用行锁定 默认情况下,innodb_api_disable_rowlock设置为OFF这意味着 memcached请求行锁定 getset操作。innodb_api_disable_rowlock设置为 ONmemcached请求表锁,而不是行锁。

innodb_api_disable_rowlock选项不是动态的。它必须在启动时在mysqld命令行中指定 或输入到MySQL配置文件中。

允许或禁止DDL

默认情况下,您可以执行DDL 操作,例如插件ALTER TABLE使用的表格daemon_memcached为避免将这些表用于高吞吐量应用程序时可能发生的减速,请innodb_api_enable_mdl在启动时启用这些表以禁用DDL操作 当通过memcached和SQL 访问相同的表时,此选项不太合适,因为它会阻止CREATE INDEX 表上的语句,这对于运行报表查询可能很重要。

将数据存储在磁盘,内存或两者中

innodb_memcache.cache_policies表指定是否将通过memcached接口写入的数据存储 到磁盘(innodb_only默认值); 在内存中,与传统的memcachedcache-only)一样; 或两者(caching)。

使用该caching设置,如果 memcached在内存中找不到密钥,它将在InnoDB表中搜索该值如果值在 表中的磁盘上更新但尚未从内存高速缓存中过期,那么getcaching设置下的调用 返回的值可能会过时InnoDB

缓存策略可以独立设定 getset(包括 incrdecr), deleteflush 操作。

例如,您可能允许getset操作查询或更新表和memcached的(使用在同一时间内存缓存caching设置),同时使 deleteflush或(使用上都在内存中拷贝只能操作 cache_only设置)。这样,删除或刷新项目只会使缓存中的项目过期,并InnoDB 在下次请求项目时表格返回最新值

MySQL的> SELECT * FROM innodb_memcache.cache_policies;
+ -------------- + ------------- ------------- + ------ + --------- + -------------- +
| policy_name | get_policy | set_policy | delete_policy | flush_policy |
+ -------------- + ------------- ------------- + ------ + --------- + -------------- +
| cache_policy | innodb_only | innodb_only | innodb_only | innodb_only |
+ -------------- + ------------- ------------- + ------ + --------- + -------------- +

MySQL的> UPDATE innodb_memcache.cache_policies SET set_policy = 'caching'
       WHERE policy_name = 'cache_policy';

innodb_memcache.cache_policies值仅在启动时读取。更改此表中的值后,请卸载并重新安装daemon_memcached 插件以确保更改生效。

MySQL的> UNINSTALL PLUGIN daemon_memcached;

MySQL的> INSTALL PLUGIN daemon_memcached soname "libmemcached.so";

14.20.5.5将DML语句调整为memcached操作

基准测试表明,daemon_memcached 插件加速DML操作(插入,更新和删除)超过加速查询。因此,考虑集中在I / O绑定的写密集型应用程序上的初始开发工作,并寻找机会将MySQL与 daemon_memcached插件一起用于新的写密集型应用程序。

单行DML语句是转化为memcached操作的最简单的语句类型INSERTaddUPDATEsetincr还是decrDELETE成为delete这些操作保证只在通过memcached接口发布时才影响一行,因为key它在表中是唯一的。

在以下SQL示例中,基于表中的配置t1引用用于memcached操作的 innodb_memcache.containers表。 key指的是下面列出的列 key_columns,并且val 是指列在下面的列 value_columns

INSERT INTO t1(key,val)VALUES(some_keysome_value);
SELECT val FROM t1 WHERE key = some_key;
UPDATE t1 SET val = new_valueWHERE key = some_key;
UPDATE t1 SET val = val + x WHERE key = some_key;
DELETE FROM t1 WHERE key = some_key;

以下TRUNCATE TABLEDELETE从表中删除所有行的语句与flush_all操作相对应 ,其中的 操作与上例中的t1配置为memcached操作的表 一样。

TRUNCATE TABLE t1;
DELETE FROM t1;

14.20.5.6在底层InnoDB表上执行DML和DDL语句

您可以通过标准SQL接口访问基础InnoDB表(test.demo_test默认情况下)。但是,有一些限制:

  • 在查询也通过memcached接口访问的表时 ,请记住, 可以将memcached操作配置为定期提交,而不是在每次写入操作之后进行提交。该行为由daemon_memcached_w_batch_size 选项控制 如果此选项设置为大于的值 1,请使用READ UNCOMMITTED查询来查找刚刚插入的行。

    MySQL的> SET SESSSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
    
    MySQL的> SELECT * FROM demo_test;
    + ------ + ------ + ------ + ------ + ----------- ------ + +  - ---- + ------ + ------ + ------ + ------ +
    | cx | cy | c1 | cz | c2 | ca | CB | c3 | cu | c4 | C5 |
    + ------ + ------ + ------ + ------ + ----------- ------ + +  - ---- + ------ + ------ + ------ + ------ +
    | NULL | NULL | a11 | NULL | 123456789 | NULL | NULL | 10 | NULL | 3 | NULL |
    + ------ + ------ + ------ + ------ + ----------- ------ + +  - ---- + ------ + ------ + ------ + ------ +
    
  • 当使用也通过memcached接口访问的SQL修改表时,可以配置memcached操作来定期启动新的事务,而不是每次读取操作。该行为由daemon_memcached_r_batch_size 选项控制 如果此选项设置为大于此值 1,则使用SQL对表进行的更改不会立即对memcached 操作可见

  • InnoDB表是IS(意向共享)或IX(意向排除)锁定用于交易中的所有操作。如果增加daemon_memcached_r_batch_size 并且 daemon_memcached_w_batch_size 大大超出 其默认值 1,则表很可能会在每个操作之间锁定,从而阻止 表上的DDL语句。

14.20.6 InnoDB memcached插件和复制

由于该daemon_memcached插件支持MySQL 二进制日志因此可以复制通过memcached接口主服务器上进行的更新以进行备份,平衡密集读取工作负载和高可用性。二进制日志记录支持所有memcached命令。

您不需要daemon_memcached从属服务器设置插件这种配置的主要优点是增加了主设备上的写入吞吐量。复制机制的速度不受影响。

以下部分介绍如何在使用daemon_memcachedMySQL复制插件时使用二进制日志功能假设您已经完成了第14.20.3节“设置InnoDB memcached插件”中描述的设置

启用InnoDB memcached二进制日志

  1. 要将daemon_memcached插件与MySQL 二进制日志一起使用,请启用 主服务器innodb_api_enable_binlog 上的配置选项 该选项只能在服务器启动时设置。您还必须使用该选项在主服务器上启用MySQL二进制日志 您可以将这些选项添加到MySQL配置文件或 mysqld命令行中。 --log-bin

    mysqld ... --log-bin --innodb_api_enable_binlog = 1
    
  2. 第16.1.2节“设置基于二进制日志文件位置的复制”中所述配置主服务器和从服务器

  3. 使用mysqldump创建主数据快照,并将快照同步到从服务器。

    主外壳> mysqldump --all-databases --lock-all-tables > dbdump.db
    从外壳>mysql < dbdump.db
    
  4. 在主服务器上,发出SHOW MASTER STATUS获取主二进制日志坐标。

    MySQL的> SHOW MASTER STATUS;
    
  5. 在从服务器上,使用CHANGE MASTER TO语句来使用主二进制日志坐标设置从服务器。

    MySQL的> CHANGE MASTER TO
           MASTER_HOST='localhost',
           MASTER_USER='root',
           MASTER_PASSWORD='',
           MASTER_PORT = 13000,
           MASTER_LOG_FILE='0.000001,
           MASTER_LOG_POS=114;
    
  6. 启动从站。

    MySQL的> START SLAVE;
    

    如果错误日志输出类似于以下内容的输出,则从设备已准备好进行复制。

    2013-09-24T13:04:38.639684Z 49 [注] Slave I / O线程:连接到
    主'root @ localhost:13000',复制开始日志'0.000001'
    在位置114
    

测试InnoDB memcached复制配置

本示例演示如何 使用memcached 和telnet 测试 InnoDB memcached复制配置以插入,更新和删除数据。MySQL客户端用于验证主服务器和从服务器上的结果。

该示例使用该demo_test表,该表由innodb_memcached_config.sql配置脚本在daemon_memcached插件的初始设置期间 创建 demo_test表包含一个示例记录。

  1. 使用该set命令插入记录test1,其中的标志值为 10,过期值为 0,cas值为1,值为 t1

    telnet 127.0.0.1 11211
    尝试127.0.0.1 ...
    连接到127.0.0.1。
    转义字符是'^]'。
    set test1 10 0 1
    t1
    STORED
    
  2. 在主服务器上,检查记录是否已插入demo_test表中。假设 demo_test表格以前未被修改,应该有两个记录。带键的示例记录AA,以及刚刚插入的记录,其中的一个键test1c1列映射到键时, c2列的值,该 c3列的标志值,该 c4列的值CAS,和 c5列的到期时间。由于未使用,到期时间设置为0。

    MySQL的> SELECT * FROM test.demo_test;
    + ------- + -------------- + ------ + ------ + ------ +
    | c1 | c2 | c3 | c4 | c5 |
    + ------- + -------------- + ------ + ------ + ------ +
    | AA | HELLO,HELLO | 8 | 0 | 0 |
    | test1 | t1 | 10 | 1 | 0 |
    + ------- + -------------- + ------ + ------ + ------ +
    
  3. 检查以确认相同记录已复制到从属服务器。

    MySQL的> SELECT * FROM test.demo_test;
    + ------- + -------------- + ------ + ------ + ------ +
    | c1 | c2 | c3 | c4 | c5 |
    + ------- + -------------- + ------ + ------ + ------ +
    | AA | HELLO,HELLO | 8 | 0 | 0 |
    | test1 | t1 | 10 | 1 | 0 |
    + ------- + -------------- + ------ + ------ + ------ +
    
  4. 使用该set命令将密钥更新为值new

    telnet 127.0.0.1 11211
    尝试127.0.0.1 ...
    连接到127.0.0.1。
    转义字符是'^]'。
    set test1 10 0 2
    new
    STORED
    

    更新被复制到从服务器(注意cas值也被更新)。

    MySQL的> SELECT * FROM test.demo_test;
    + ------- + -------------- + ------ + ------ + ------ +
    | c1 | c2 | c3 | c4 | c5 |
    + ------- + -------------- + ------ + ------ + ------ +
    | AA | HELLO,HELLO | 8 | 0 | 0 |
    | test1 | 新的| 10 | 2 | 0 |
    + ------- + -------------- + ------ + ------ + ------ +
    
  5. test1使用delete命令 删除记录

    telnet 127.0.0.1 11211
    尝试127.0.0.1 ...
    连接到127.0.0.1。
    转义字符是'^]'。
    delete test1
    DELETED
    

    delete操作复制到从站时,从站上的test1记录也被删除。

    MySQL的> SELECT * FROM test.demo_test;
    + ---- + -------------- + ------ + ------ + ------ +
    | c1 | c2 | c3 | c4 | c5 |
    + ---- + -------------- + ------ + ------ + ------ +
    | AA | HELLO,HELLO | 8 | 0 | 0 |
    + ---- + -------------- + ------ + ------ + ------ +
    
  6. 使用该flush_all命令从表中删除所有行

    telnet 127.0.0.1 11211
    尝试127.0.0.1 ...
    连接到127.0.0.1。
    转义字符是'^]'。
    flush_all
    
    MySQL的> SELECT * FROM test.demo_test;
    空集(0.00秒)
    
  7. Telnet到主服务器并输入两条新记录。

    telnet 127.0.0.1 11211
    尝试127.0.0.1 ...
    连接到127.0.0.1。
    转义字符是'^]'
    set test2 10 0 4
    again
    STORED
    set test3 10 0 5
    again1
    STORED
    
  8. 确认两条记录已复制到从属服务器。

    MySQL的> SELECT * FROM test.demo_test;
    + ------- + -------------- + ------ + ------ + ------ +
    | c1 | c2 | c3 | c4 | c5 |
    + ------- + -------------- + ------ + ------ + ------ +
    | test2 | 再次| 10 | 4 | 0 |
    | test3 | again1 | 10 | 5 | 0 |
    + ------- + -------------- + ------ + ------ + ------ +
    
  9. 使用该flush_all命令从表中删除所有行

    telnet 127.0.0.1 11211
    尝试127.0.0.1 ...
    连接到127.0.0.1。
    转义字符是'^]'。
    flush_all
    
  10. 检查以确保该flush_all 操作已在副服务器上复制。

    MySQL的> SELECT * FROM test.demo_test;
    空集(0.00秒)
    

InnoDB memcached二进制日志注释

二进制日志格式:

  • 大多数memcached操作都映射到 DML语句(类似于插入,删除,更新)。由于MySQL服务器没有处理实际的SQL语句,因此所有的 memcached命令(除了 flush_all)都使用基于行的复制(RBR)日志记录,这与任何服务器binlog_format设置无关

  • 分布式缓存 flush_all命令被映射到 TRUNCATE TABLE命令。由于 DDL命令只能使用基于语句的日志记录,因此flush_all 通过发送TRUNCATE TABLE语句来复制命令

交易方式:

14.20.7 InnoDB memcached插件内部

用于InnoDB memcached Plugin的InnoDB API

InnoDB 分布式缓存 引擎访问InnoDBInnoDB的API,其中大部分是直接从嵌入式采纳InnoDBInnoDBAPI函数作为回调函数传递给 InnoDB memcached引擎。InnoDBAPI函数InnoDB直接访问表,大多数DML操作除外 TRUNCATE TABLE

memcached命令是通过InnoDB memcached API实现的下表概述了 memcached 命令如何映射到DML或DDL操作。

表14.16 memcached命令和相关的DML或DDL操作

memcached命令 DML或DDL操作
get 读/取命令
set 搜索后跟一个INSERTUPDATE(取决于是否存在密钥)
add 搜索后跟一个INSERTor UPDATE
replace 搜索后跟一个 UPDATE
append 搜索后跟一个UPDATE(将数据附加到结果之前UPDATE
prepend 一个搜索后跟一个UPDATE(在数据之前加上数据UPDATE
incr 搜索后跟一个 UPDATE
decr 搜索后跟一个 UPDATE
delete 搜索后跟一个 DELETE
flush_all TRUNCATE TABLE (DDL)

InnoDB memcached插件配置表

本节介绍daemon_memcached插件使用的配置表 cache_policies表, config_options表, containers表是由创建 innodb_memcached_config.sql的配置脚本innodb_memcache数据库。

MySQL的> USE innodb_memcache;
数据库改变
MySQL的> SHOW TABLES;
+ --------------------------- +
| Tables_in_innodb_memcache |
+ --------------------------- +
| cache_policies |
| config_options |
| 容器|
+ --------------------------- +

cache_policies表

cache_policies表定义了InnoDB memcached安装的缓存策略您可以指定单个策略getsetdelete,和 flush单一高速缓存策略中的操作。所有操作的默认设置是 innodb_only

  • innodb_onlyInnoDB用作数据存储。

  • cache-only:使用 memcached引擎作为数据存储。

  • caching:使用两者 InnoDBmemcached引擎作为数据存储。在这种情况下,如果memcached在内存中找不到密钥,它将在InnoDB表中搜索该值

  • disable:禁用缓存。

表14.17 cache_policies列

描述
policy_name 缓存策略的名称。默认缓存策略名称是 cache_policy
get_policy 获取操作的缓存策略。有效值是 innodb_onlycache-onlycaching,或disabled默认设置是 innodb_only
set_policy 设置操作的缓存策略。有效值是 innodb_onlycache-onlycaching,或disabled默认设置是 innodb_only
delete_policy 用于删除操作的缓存策略。有效值是 innodb_onlycache-onlycaching,或disabled默认设置是 innodb_only
flush_policy 刷新操作的缓存策略。有效值是 innodb_onlycache-onlycaching,或disabled默认设置是 innodb_only

config_options表

config_options表存储 可以在运行时使用SQL更改的与memcached相关的设置。支持的配置选项是separatortable_map_delimiter

表14.18 config_options列

描述
Name memcached相关配置选项的名称config_options支持以下配置选项
  • separator:用于在有多个value_columns 定义的情况下将长字符串的值分隔为单独的值默认情况下,这 separator是一个 |字符。例如,如果将col1, col2定义为值列,并且将其定义|为分隔符,则可以发出以下 memcached命令分别将值插入col1col2

    设置键盘10 0 19
    valuecolx | valuecoly
    

    valuecol1x存储 col1valuecoly存储在中 col2

  • table_map_delimiter@@在使用键名称中表示法访问特定表中的键时,用于分隔模式名称和表名称的字符例如,@@t1.some_key@@t2.some_key具有相同的密钥值,但被存储在不同的表中。

Value 分配给memcached相关配置选项的值。

容器表

containers表是三个配置表中最重要的一个。每个InnoDB 用于存储memcached值的containers都必须在表中包含一个条目该条目提供了InnoDB 表格列和容器表格列之间的映射,这是memcached使用 InnoDB表格所必需的

containers表包含test.demo_testinnodb_memcached_config.sql 配置脚本创建表的默认条目要将 daemon_memcached插件与您自己的 InnoDB表一起使用,您必须在containers表中创建一个条目

表14.19容器列

描述
name 给容器的名称。如果InnoDB没有使用@@ 表示法按名称请求表,则daemon_memcached插件将使用值为 InnoDB如果没有这样的条目,则表中的第一个条目按字母顺序排列 (升序),从而确定默认 表。containers.namedefaultcontainersnameInnoDB
db_schema InnoDB表所在的数据库的名称这是一个必需的值。
db_table InnoDB存储memcached的名称这是一个必需的值。
key_columns InnoDB表中包含memcached操作的查找键值的列这是一个必需的值。
value_columns InnoDB存储memcached数据表列(一个或多个) 可以使用表中指定的分隔符指定多列 innodb_memcached.config_options默认情况下,分隔符是管道字符(|)。要指定多个列,请使用定义的分隔符分隔它们。例如: col1|col2|col3这是一个必需的值。
flags InnoDB用作memcached的标志(用户定义的数值,与主值一起存储和检索)表列 如果memcached值映射到多个列,则标志值可用作某些操作(如incrprepend的列说明符 ,以便在指定列上执行操作。例如,如果您已将映射 到三个 表列,并且只希望在一列上执行增量操作,请使用 列来指定列。如果你不使用value_columnsInnoDBflagsflags列,设置一个值0来表示它未被使用。
cas_column InnoDB存储比较和交换(cas)值表列。cas_column值与memcached散列对不同服务器的请求以及缓存内存中数据的方式有关由于InnoDB memcached插件与单个memcached守护进程紧密集成,并且内存中缓存机制由MySQL和 InnoDB缓冲池处理,因此很少需要此列。如果您不使用此列,请将值设置0为表示未使用。
expire_time_column InnoDB存储到期值表列。expire_time_column值与memcached散列对不同服务器的请求以及缓存内存中数据的方式有关由于InnoDB memcached插件与单个memcached守护进程紧密集成,并且内存中缓存机制由MySQL和 InnoDB缓冲池处理,因此很少需要此列。如果您不使用此列,请设置值0以指示该列未使用。最长过期时间定义为INT_MAX32 或2147483647秒(约68年)。
unique_idx_name_on_key 键列上索引的名称。它必须是一个独特的索引。它可以是主键辅助索引最好使用InnoDB表格的主键 使用主键可避免使用辅助索引时执行的查找。您无法memcached查找制作 覆盖索引 ; 如果您尝试通过键和值列定义复合二级索引,则会返回错误。InnoDB

容器表列约束
  • 你必须提供一个值db_schemadb_namekey_columnsvalue_columnsunique_idx_name_on_key指定 0flagscas_column以及 expire_time_column如果它们是未使用。如果不这样做可能会导致您的设置失败。

  • key_columnsmemcached密钥的最大限制 是250个字符,这由memcached执行映射的键必须是非空CHARVARCHAR类型。

  • value_columns:必须被映射到 CHARVARCHAR或者 BLOB柱。没有长度限制,值可以为NULL。

  • cas_column:该cas 值是一个64位整数。它必须映射到 BIGINT至少8个字节。如果您不使用此列,请将值设置 0为表示未使用。

  • expiration_time_column:必须映射到 INTEGER至少4个字节。到期时间定义为Unix时间的32位整数(1970年1月1日以来的秒数,32位值)或从当前时间开始的秒数。对于后者,秒数不得超过60 * 60 * 24 * 30(30天内的秒数)。如果客户端发送的号码较大,服务器认为它是一个真正的Unix时间值,而不是与当前时间的偏移量。如果您不使用此列,请将值设置 0为表示未使用。

  • flags:必须映射到 INTEGER至少32位,并且可以为NULL。如果您不使用此列,请将值设置0为表示未使用。

在插件加载时执行预检查以强制实施列约束。如果发现不匹配,则插件未加载。

多值列映射
  • 在插件初始化期间,当InnoDB memcached配置了containers表中定义的信息时,将containers.value_columns根据映射InnoDB验证定义的每个映射列 如果InnoDB映射多个表列,则会进行检查以确保每列均存在并且是正确的类型。

  • 在运行时,对于memcached插入操作,如果分隔值的数量多于映射列的数量,则仅采用映射值的数量。例如,如果有6个映射列,并且提供了7个定界值,则只会采用前6个定界值。第七个分隔值被忽略。

  • 如果分隔值少于映射列,则未填充列设置为NULL。如果未填充的列不能设置为NULL,则插入操作将失败。

  • 如果一个表的列数多于映射值,则额外的列不会影响结果。

demo_test示例表

innodb_memcached_config.sql 配置脚本创建一个demo_test 表中的test数据库,它可以用来验证InnoDB memcached的 设置完成后立即安装插件。

innodb_memcached_config.sql 配置脚本还创建了一个条目 demo_test表中的 innodb_memcache.containers表。

MySQL的> SELECT * FROM innodb_memcache.containers\G
*************************** 1. row ******************** *******
                  名称:aaa
             db_schema:测试
              db_table:demo_test
           key_columns:c1
         value_columns:c2
                 标志:c3
            cas_column:c4
    expire_time_column:c5
unique_idx_name_on_key:PRIMARY

MySQL的> SELECT * FROM test.demo_test;
+ ---- + ------------------ + ------ + ------ + ------ +
| c1 | c2 | c3 | c4 | c5 |
+ ---- + ------------------ + ------ + ------ + ------ +
| AA | HELLO,HELLO | 8 | 0 | 0 |
+ ---- + ------------------ + ------ + ------ + ------ +

14.20.8解决InnoDB memcached插件故障

本节介绍使用InnoDB memcached插件时可能遇到的问题

  • 如果在MySQL错误日志中遇到以下错误,服务器可能无法启动:

    未能为打开的文件设置rlimit。尝试以root身份运行或请求较小的maxconns值。

    错误消息来自memcached 守护进程。一种解决方法是提高操作系统对打开文件数量的限制。用于检查和增加打开文件限制的命令因操作系统而异。这个例子显示了Linux和OS X的命令:

    #Linux
    外壳> ulimit -n
    1024
    shell> ulimit -n 4096
    shell>ulimit -n
    4096
    
    #OS X
    外壳> ulimit -n
    256
    shell> ulimit -n 4096
    shell>ulimit -n
    4096
    

    另一种解决方案是减少memcached 守护进程允许的并发连接数为此,请 在MySQL配置文件配置参数中对-c memcached选项 进行编码daemon_memcached_option-c选项的默认值为1024。

    的[mysqld]
    ...
    loose-daemon_memcached_option =' -  c 64'
    
  • 要解决 memcached守护程序无法存储或检索InnoDB表数据的问题,请 在MySQL配置文件配置参数中对-vvv memcached选项进行编码 daemon_memcached_option检查MySQL错误日志以获取与memcached相关的调试输出 操作

    的[mysqld]
    ...
    松daemon_memcached_option = ' -  VVV'
    
  • 如果指定保存memcached 值的是错误的数据类型(如数字类型而不是字符串类型),则尝试存储键/值对将失败,并且不会显示特定的错误代码或消息。

  • 如果该daemon_memcached插件导致MySQL服务器启动问题,则可以daemon_memcached在解决问题时通过在该项下添加此行来临时禁用该 插件 [mysqld]在MySQL配置文件中

    daemon_memcached = OFF
    

    例如,如果您INSTALL PLUGIN在运行innodb_memcached_config.sql配置脚本来设置必要的数据库和表之前运行语句 ,则服务器可能会崩溃并且无法启动。如果您错误地配置了一个条目,服务器也可能无法启动 innodb_memcache.containers表中

    卸载memcached MySQL实例插件,请发出以下语句:

    MySQL的> UNINSTALL PLUGIN daemon_memcached;
    
  • 如果daemon_memcached在每个实例中启用插件的同一台计算机上运行MySQL的多个实例,请使用 daemon_memcached_option 配置参数为每个插件指定唯一的 memcached端口 daemon_memcached

  • 如果SQL语句找不到InnoDB 表或表中找不到数据,但 memcached API调用检索预期的数据,则InnoDB表中可能缺少的条目 innodb_memcache.containers,或者您可能没有InnoDB 通过发布来切换到正确的表a getset使用 符号的请求 更改了的现有条目,也会发生此问题 @@table_idinnodb_memcache.containers而不重新启动MySQL服务器,自由格式的存储机制非常灵活,可以让您存储或检索多列值的请求,例如 col1|col2|col3即使守护进程正在使用test.demo_test将值存储在单个列中,也可能仍然有效

  • 在定义您自己的InnoDB用于daemon_memcached插件的表并将表中的列定义为时NOT NULL,请确保NOT NULL在将表的记录插入表中时提供值 innodb_memcache.containers如果记录INSERT语句 innodb_memcache.containers包含的分隔值少于映射列的分隔值,则将未填充的列设置为NULL尝试将NULL值插入NOT NULL列会导致 INSERT失败,这可能只有在重新初始化daemon_memcached插件以将更改应用到innodb_memcache.containers后才会变得明显

  • 如果cas_columnexpire_time_column该字段 innodb_memcached.containers的表被设置为NULL,尝试加载时,返回以下错误的memcached 插件:

    InnoDB_Memcached:配置表'containers'中的第6列
    数据库'innodb_memcache'具有无效的NULL值。
    

    memcached的插件拒绝的使用 NULLcas_columnexpire_time_column列。将这些列的值设置为0列未使用时的值

  • 随着memcached密钥和值的长度增加,您可能会遇到大小和长度限制。

    • 当密钥超过250个字节时, memcached操作返回错误。目前这是memcached中的一个固定限制

    • InnoDB如果值超过768字节,3072字节或innodb_page_size值的一半,则可能会遇到表限制 如果您打算在值列上创建索引以使用SQL在该列上运行报表生成查询,则这些限制主要适用。有关详细信息请参见 第14.8.1.7节“InnoDB表限制”

    • 键值组合的最大大小为1 MB。

  • 如果您在不同版本的MySQL服务器之间共享配置文件,那么使用该daemon_memcached插件的最新配置选项可能会导致旧版本MySQL的启动错误。为避免兼容性问题,请使用loose带选项名称前缀。例如,使用 loose-daemon_memcached_option='-c 64' 而不是daemon_memcached_option='-c 64'

  • 没有限制或检查来验证字符集设置。memcached以字节为单位存储和检索键和值,因此不是字符集敏感的。但是,您必须确保 memcached客户端和MySQL表使用相同的字符集。

  • memcached连接被阻止访问包含索引虚拟列的表。访问索引虚拟列需要回调服务器,但 memcached连接无法访问服务器代码。

14.21 InnoDB故障排除

以下一般准则适用于故障排除 InnoDB问题:

  • 当一个操作失败或者您怀疑有bug时,请查看MySQL服务器错误日志(参见第5.4.2节“错误日志”)。 第B.3节“服务器错误代码和消息”提供InnoDB了您可能遇到的一些常见特定错误的疑难解答信息

  • 如果失败与 死锁有关,请innodb_print_all_deadlocks 启用选项,以便将有关每个死锁的详细信息打印到MySQL服务器错误日志中。有关死锁的信息,请参见第14.5.5节“InnoDB中的死锁”

  • InnoDB数据字典相关的问题包括失败的CREATE TABLE 语句(孤立表文件),无法打开 InnoDB文件以及系统找不到指定错误的路径有关这些问题和错误的信息,请参见 第14.21.3节“InnoDB数据字典操作故障排除”

  • 在进行故障排除时,通常最好从命令提示符运行MySQL服务器,而不是通过 mysqld_safe或Windows服务运行。然后,您可以看到mysqld向控制台输出的内容,从而更好地掌握正在发生的事情。在Windows上,启动mysqld并使用 --console选项将输出定向到控制台窗口。

  • 启用InnoDB监视器以获取有关问题的信息(请参见 第14.17节“InnoDB监视器”)。如果问题与性能相关,或者您的服务器似乎挂起,则应启用标准的Monitor以打印有关内部状态的信息InnoDB如果问题出在锁上,请启用锁定监视器。如果问题出现在表创建,表空间或数据字典操作中,请参阅 InnoDB信息模式系统表以检查InnoDB内部数据字典的内容。

    InnoDBInnoDB在以下情况下暂时启用标准 监视器输出:

    • 一个很长的信号量等待

    • InnoDB 无法在缓冲池中找到空闲块

    • 超过67%的缓冲池被锁堆或自适应散列索引占用

  • 如果您怀疑某个表已损坏,请CHECK TABLE在该表上运行

14.21.1排除InnoDB I / O问题

InnoDBI / O问题 的故障排除步骤取决于发生问题的时间:在MySQL服务器启动期间,或者由于文件系统级别的问题导致DML或DDL语句失败的正常操作期间。

初始化问题

如果InnoDB尝试初始化表空间或其日志文件时出现问题,请删除由InnoDB所有 ibdata文件和所有ib_logfile文件创建的所有 文件。如果您已经创建了一些 InnoDB表,那么也可以从MySQL数据库目录中删除.frm这些表的相应 文件以及任何 .ibd文件(如果您使用多个表空间)。然后InnoDB再次尝试 数据库创建。为了最简单的故障排除,请从命令提示符处启动MySQL服务器,以便查看发生了什么。

运行时问题

如果InnoDB在文件操作过程中打印操作系统错误,通常该问题有以下解决方案之一:

  • 确保InnoDB数据文件目录和InnoDB日志目录存在。

  • 确保mysqld具有在这些目录中创建文件的访问权限。

  • 确保mysqld可以读取正确的 my.cnfmy.ini 选项文件,以便它以您指定的选项开始。

  • 确保磁盘未满并且您没有超出任何磁盘配额。

  • 确保您为子目录和数据文件指定的名称不会发生冲突。

  • 再次检查innodb_data_home_dirinnodb_data_file_path的语法 特别是,MAXinnodb_data_file_path选项中的任何都是硬性限制,超过该限制会导致严重错误。

14.21.2强制InnoDB恢复

要调查数据库页面损坏情况,可以使用数据库转储表格 SELECT ... INTO OUTFILE通常,以这种方式获得的大部分数据是完整的。严重的损坏可能会导致语句或 后台操作崩溃或断言,甚至导致前滚恢复崩溃。在这种情况下,您可以使用该 选项强制存储引擎启动,同时防止后台操作运行,以便转储表。例如,可以在重新启动服务器之前将以下行添加到选项文件部分: SELECT * FROM tbl_nameInnoDBInnoDBinnodb_force_recoveryInnoDB[mysqld]

的[mysqld]
innodb_force_recovery = 1
警告

innodb_force_recovery 在紧急情况下, 只能设置为大于0的值,以便您可以启动InnoDB并转储您的表格。在此之前,请确保您有数据库的备份副本,以备需要重新创建时使用。4或更大的值可能会永久损坏数据文件。innodb_force_recovery在成功测试数据库的单独物理副本上的设置后,只能在生产服务器实例上使用 4或更大的设置。强制InnoDB恢复时,应始终 innodb_force_recovery=1按照需要逐步增加值。

innodb_force_recovery默认情况下为0(没有强制恢复的正常启动)。允许的非零值 innodb_force_recovery 1到6.较大的值包括较小值的功能。例如,值3包括值1和2的所有功能。

如果您可以将表格转储innodb_force_recovery为3或更少值,那么相对安全的是只有损坏的单个页面上的一些数据丢失。值4或更大被认为是危险的,因为数据文件可能永久损坏。由于数据库页面处于过时状态,因此值6被认为是非常激烈的,这反过来可能会在B树 和其他数据库结构中引入更多的损坏

作为安全措施,大于0 InnoDB防止 INSERTUPDATEDELETE操作 innodb_force_recoveryinnodb_force_recovery 设置为4或更大的位置InnoDB处于只读模式。

  • 1SRV_FORCE_IGNORE_CORRUPT

    即使它检测到损坏的页面,也让服务器运行 试图 跳过损坏的索引记录和页面,这有助于转储表格。 SELECT * FROM tbl_name

  • 2SRV_FORCE_NO_BACKGROUND

    防止主线程和任何清除线程运行。如果在清除操作期间发生崩溃 ,则此恢复值会阻止它。

  • 3SRV_FORCE_NO_TRX_UNDO

    崩溃恢复 不运行事务 回滚

  • 4SRV_FORCE_NO_IBUF_MERGE

    防止插入缓冲区合并操作。如果他们会导致崩溃,不会这样做。不计算表格 统计信息该值可能会永久损坏数据文件。使用此值后,准备放弃并重新创建所有二级索引。设置 InnoDB为只读。

  • 5SRV_FORCE_NO_UNDO_LOG_SCAN

    启动数据库时 不会查看撤消日志InnoDB即使未完成的事务也被视为已提交。该值可能会永久损坏数据文件。设置InnoDB为只读。

  • 6SRV_FORCE_NO_LOG_REDO

    不会执行与恢复有关的重做日志前 滚。该值可能会永久损坏数据文件。使数据库页面处于过时状态,这反过来可能将更多的损坏引入B树和其他数据库结构。设置 InnoDB为只读。

你可以SELECT从表中转储它们。如果 innodb_force_recovery值为3或更少,则可以使用表格DROPCREATE表格。DROP TABLE也支持innodb_force_recovery大于3 值,直到MySQL 5.7.17。从MySQL 5.7.18开始, DROP TABLE不允许使用 innodb_force_recovery大于4值。

如果您知道给定的表在回滚时导致崩溃,则可以将其删除。如果遇到失败的批量导入导致的失控回滚ALTER TABLE,您可以终止mysqld进程,并设置 innodb_force_recovery3在没有回滚的情况下启动数据库,然后DROP设置导致失控回滚的表。

如果表数据中的腐败使您无法转储整个表内容,则使用 ORDER BY primary_key DESC子句可能能够在损坏的部分之后转储表的部分。

如果一个高innodb_force_recovery 值是必需的开始InnoDB,有可能是,可能导致(含有查询的复杂查询损坏的数据结构WHEREORDER BY或其它条款)失败。在这种情况下,您可能只能运行基本SELECT * FROM t 查询。

14.21.3 InnoDB数据字典操作故障排除

有关表定义的信息既存储在.frm文件中,也存储 在InnoDB 数据字典中如果您移动.frm文件,或者如果服务器在数据字典操作过程中崩溃,这些信息源可能会变得不一致。

如果数据字典损坏或一致性问题阻止您启动InnoDB,请参见 第14.21.2节“强制InnoDB恢复”以获取有关手动恢复的信息。

由于孤立表,CREATE TABLE失败

不同步数据字典的一个症状是 CREATE TABLE语句失败。如果发生这种情况,请查看服务器的错误日志。如果日志说该表已经存在于 InnoDB内部数据字典中,那么在InnoDB表空间文件中有一个没有相应.frm文件的孤立表错误消息如下所示:

InnoDB:错误:InnoDB内部已经存在table test / parent
InnoDB:数据字典。您是否删除了.frm文件
InnoDB:并没有使用DROP TABLE?你用过DROP DATABASE吗?
InnoDB:用于MySQL版本<= 3.23.43的InnoDB表?
InnoDB:参见InnoDB手册的限制部分。
InnoDB:您可以通过删除InnoDB中的孤立表
InnoDB:在另一个中创建具有相同名称的InnoDB表
InnoDB:数据库并将.frm文件移动到当前数据库。
InnoDB:然后MySQL认为表存在,并且DROP TABLE将会
InnoDB:成功。

您可以按照错误消息中给出的说明删除孤立表。如果您仍然无法DROP TABLE成功使用 ,则问题可能是由于mysql客户端中的名称完成 要解决此问题,请使用该 选项启动mysql客户端, --skip-auto-rehash然后重试DROP TABLE(当名称完成时,mysql会尝试构造一个表名列表,当刚刚描述的问题存在时,它将失败。)

无法打开数据文件

随着innodb_file_per_table 启用(默认值),下面的消息可能会在启动时出现,如果一个 文件的每个表的 表空间文件(.ibd文件)是丢失:

[错误] InnoDB:文件操作中的操作系统错误编号2。
[错误] InnoDB:错误意味着系统找不到指定的路径。
[错误] InnoDB:无法打开数据文件为只读:'./test/t1.ibd'操作系统错误:71
[警告] InnoDB:忽略表空间`test / t1`,因为它无法打开。

要解决这些消息,请发出DROP TABLE语句以从数据字典中删除有关缺少表的数据。

无法打开文件错误

不同步数据字典的另一个症状是MySQL打印出一个无法打开InnoDB文件的错误

错误1016:无法打开文件:'child2.ibd'。(错误:1)

在错误日志中你可以找到这样的消息:

InnoDB:从内部数据字典中找不到表test / child2
InnoDB:虽然InnoDB的.frm文件存在。可能是你
InnoDB:已经删除并重新创建了InnoDB数据文件,但已经忘记了
InnoDB:删除InnoDB表的相应.frm文件?

这意味着有一个.frm 没有相应表格的孤儿文件 InnoDB您可以.frm通过手动删除孤立 文件来删除它。

孤儿中间表

如果MySQL在就地ALTER TABLE操作过程中退出 ALGORITHM=INPLACE),则可能会留下一个孤立的中间表,以占用系统空间。此外,在其他空白的常规表空间中的孤立中间表 可以防止您丢弃常规的表空间本节介绍如何识别和删除孤儿中间表。

中间表名称以#sql-ib前缀(例如, #sql-ib87-856498050开头 附带的 .frm文件有一个 #sql-*前缀,名称不同(例如#sql-36ab_2.frm)。

要识别系统上的孤立中间表,您可以查询 INFORMATION_SCHEMA.INNODB_SYS_TABLES寻找开头的表名#sql如果原始表驻留在每个 文件表的表 空间中,#sql-*.ibd则孤立中间表的表空间文件( 文件)应该在数据库目录中可见。

SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE'%#sql%';

要删除孤立中间表,请执行以下步骤:

  1. 在数据库目录中,重命名该 #sql-*.frm文件以匹配孤立中间表的基本名称:

    外壳> mv #sql-36ab_2.frm #sql-ib87-856498050.frm
    
    注意

    如果没有.frm文件,可以重新创建它。.frm文件必须与孤立中间表具有相同的表模式(它必须具有相同的列和索引),并且必须放置在孤立中间表的数据库目录中。

  2. 通过发出一条DROP TABLE语句来 删除孤立中间表, #mysql50#在表名前加上表名,并用反引号括起表名。例如:

    MySQL的> DROP TABLE `#mysql50##sql-ib87-856498050`;
    

    #mysql50#前缀告诉MySQL忽略file name safe encoding在MySQL 5.1中引入的。在反引号中包含表名是在具有特殊字符(例如 ”)的表名上执行SQL语句所必需的

注意

如果在ALTER TABLE将表移动到其他表空间的就地操作期间发生崩溃 ,恢复过程会将该表恢复到其原始位置,但在目标表空间中保留孤立中间表。

孤儿临时表

如果MySQL在表复制ALTER TABLE操作(ALGORITHM=COPY的中间退出 ,那么您可能会留下一个孤立的临时表,这会占用系统空间。另外,在其他空的常规表空间中的孤立临时表 可以防止您丢弃常规表空间本节介绍如何识别和删除孤立的临时表。

孤儿临时表名称以#sql-前缀(例如, #sql-540_3开头 随附的 .frm文件与孤立临时表具有相同的基本名称。

注意

如果没有.frm文件,可以重新创建它。.frm文件必须与孤立临时表具有相同的表架构(它必须具有相同的列和索引),并且必须放置在孤立临时表的数据库目录中。

要识别系统上的孤立临时表,您可以查询 INFORMATION_SCHEMA.INNODB_SYS_TABLES寻找开头的表名#sql如果原始表驻留在每个 文件表的表 空间中,#sql-*.ibd则孤立临时表的表空间文件( 文件)应该在数据库目录中可见。

SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE'%#sql%';

要删除一个孤立的临时表,通过发出一条DROP TABLE语句来删除这个表,在表 名的前面添加一个表,#mysql50#并用反引号括起表名。例如:

MySQL的> DROP TABLE `#mysql50##sql-540_3`;

#mysql50#前缀告诉MySQL忽略 file name safe encoding在MySQL 5.1中引入的。在反引号中包含表名是在具有特殊字符(例如 ”)的表名上执行SQL语句所必需的

表空间不存在

innodb_file_per_table 启用,如果可能会出现以下消息 .frm.ibd文件(或两者)丢失:

InnoDB:在InnoDB数据字典中有表空间id N
InnoDB:但是具有该id或名称的表空间不存在。
InnoDB:你删除或移动了.ibd文件?
InnoDB:这也可能是使用CREATE TEMPORARY TABLE创建的表
InnoDB:其中的.ibd和.frm文件会自动删除MySQL,但是
InnoDB:表仍然存在于InnoDB内部数据字典中。

如果发生这种情况,请尝试以下过程来解决问题:

  1. .frm在其他数据库目录中 创建一个匹配文件,并将其复制到孤立表所在的数据库目录。

  2. 发布DROP TABLE原始表格。这应该成功删除该表,并 InnoDB应该向错误日志中显示.ibd文件丢失的警告

还原孤立文件 - 每表ibd文件

本过程介绍了如何将每个文件独立文件 还原 .ibd到另一个MySQL实例。如果系统表空间丢失或不可恢复,并且您想要.idb 在新的MySQL实例上恢复文件备份,则可以使用此过程

该过程不支持 常规表空间 .ibd文件。

该过程假定您只有 .ibd文件备份,您正在恢复到最初创建孤立.idb文件的相同版本的MySQL ,并且该 .idb文件备份是干净的。有关创建干净备份的信息请参见 第14.8.1.3节“移动或复制InnoDB表”

第14.7.6节“将文件 - 表 - 表空间复制到另一个实例” 概述的表空间复制限制 适用于此过程。

  1. 在新的MySQL实例上,重新创建具有相同名称的数据库中的表。

    MySQL的> CREATE DATABASE sakila;
    
    MySQL的> USE sakila;
    
    MySQL的> CREATE TABLE actor (
             actor_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
             first_name VARCHAR(45) NOT NULL,
             last_name VARCHAR(45) NOT NULL,
             last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
             PRIMARY KEY  (actor_id),
             KEY idx_actor_last_name (last_name)
           )ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
  2. 放弃新创建的表格的表空间。

    MySQL的> ALTER TABLE sakila.actor DISCARD TABLESPACE;
    
  3. .idb备份目录中的孤立文件复制到新的数据库目录。

    外壳> cp /backup_directory/actor.ibd path/to/mysql-5.7/data/sakila/
    
  4. 确保.ibd文件具有必要的文件权限。

  5. 导入孤立.ibd文件。发出警告,指示InnoDB将尝试导入文件而无需模式验证。

    MySQL的> ALTER TABLE sakila.actor IMPORT TABLESPACE; SHOW WARNINGS;    
    查询OK,0行受影响,1个警告(0.15秒)
    
    警告| 1810 | InnoDB:IO读取错误:(2,没有这样的文件或目录)
    打开“./sakila/actor.cfg”时出错,将尝试导入
    没有模式验证
    
  6. 查询表格以验证.ibd 文件是否成功恢复。

    MySQL的> SELECT COUNT(*) FROM sakila.actor;
    + ---------- +
    | count(*)|
    + ---------- +
    | 200 |
    + ---------- +
    

14.21.4 InnoDB错误处理

以下各项介绍了如何InnoDB 执行错误处理。InnoDB有时仅回滚失败的语句,有时回滚整个事务。

  • 如果空间中的文件空间 Table is full不足,则会发生MySQL 错误并 InnoDB回滚SQL语句。

  • 一个事务死锁 导致InnoDB回滚整个 事务发生这种情况时重试整个事务。

    锁等待超时会导致InnoDB仅回滚等待锁的单个语句并遇到超时。(要使整个事务回滚,请使用该--innodb_rollback_on_timeout 选项启动服务器 。)如果使用当前行为,或者使用整个事务,请重试该语句 --innodb_rollback_on_timeout

    在繁忙的服务器上,死锁和锁等待超时都是正常的,应用程序必须知道它们可能发生并通过重试来处理它们。通过在事务和提交期间对数据进行的第一次更改之间尽可能少地工作,可以使它们变得不太可能,因此可以在尽可能短的时间内尽可能保持尽可能少的行数。有时,在不同的交易之间分工可能是实用而有用的。

    由于死锁或锁定等待超时而发生事务回滚时,它会取消事务内语句的效果。但是,如果启动事务语句是 START TRANSACTIONBEGIN 语句,回滚不会取消该语句。进一步的SQL语句成为交易的一部分,直到发生COMMITROLLBACK或某些SQL语句导致隐式提交。

  • 如果您没有IGNORE在语句中指定选项,则重复键错误会回滚SQL 语句。

  • A row too long error回滚SQL语句。

  • 其他错误大多由MySQL层代码(在InnoDB存储引擎级别之上检测到,并且它们回滚相应的SQL语句。锁不会在单个SQL语句的回滚中释放。

在隐式回滚期间,以及执行显式 ROLLBACKSQL语句期间,SHOW PROCESSLIST 显示相关连接Rolling backState列。

原文